From 68d9daee4e70426e24028f868b0c82ba554b4078 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 19 Jun 2024 12:28:11 -0700 Subject: [PATCH 01/87] Don't include "v" in tag name (#879) --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 61d91e6a1..b4f3d0068 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ version: ## Bump version and push to release branch. .PHONY: publish publish: ## Push git tag and publish version to PyPI. - @git tag v$$(poetry version -s) + @git tag $$(poetry version -s) @git push --tags @poetry build @poetry publish From b0e781cdf70bb76681adabdb1c816425e817864e Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 19 Jun 2024 13:54:48 -0700 Subject: [PATCH 02/87] Release/v0.27.0 (#880) Co-authored-by: dylanholmes <4370153+dylanholmes@users.noreply.github.com> Co-authored-by: CJ Kindel Co-authored-by: Andrew French Co-authored-by: Vasily Vasinov Co-authored-by: Matt Vallillo Co-authored-by: Michal Co-authored-by: Zach Giordano <32624672+zachgiordano@users.noreply.github.com> Co-authored-by: Ikko Eltociear Ashimine Co-authored-by: torabshaikh Co-authored-by: Aodhan Roche Co-authored-by: Kyle Roche Co-authored-by: Emily Danielson <2302515+emjay07@users.noreply.github.com> --- .coveragerc | 33 +- .gitignore | 5 +- CHANGELOG.md | 73 ++- Makefile | 2 +- docs/examples/amazon-dynamodb-sessions.md | 4 +- docs/examples/multi-agent-workflow.md | 46 +- docs/griptape-framework/data/artifacts.md | 4 +- docs/griptape-framework/data/loaders.md | 20 +- .../drivers/conversation-memory-drivers.md | 6 +- .../drivers/embedding-drivers.md | 63 +- .../drivers/event-listener-drivers.md | 8 +- .../drivers/image-generation-drivers.md | 4 +- .../drivers/image-query-drivers.md | 10 +- .../drivers/prompt-drivers.md | 351 +++-------- .../griptape-framework/drivers/sql-drivers.md | 8 +- .../drivers/structure-run-drivers.md | 4 +- .../drivers/vector-store-drivers.md | 18 +- .../drivers/web-scraper-drivers.md | 4 +- .../engines/audio-engines.md | 4 +- .../engines/extraction-engines.md | 4 +- .../engines/image-generation-engines.md | 8 +- .../engines/image-query-engines.md | 25 - .../engines/query-engines.md | 35 +- .../engines/summary-engines.md | 4 +- docs/griptape-framework/misc/tokenizers.md | 47 +- docs/griptape-framework/structures/config.md | 2 +- .../structures/conversation-memory.md | 2 +- .../griptape-framework/structures/rulesets.md | 2 +- .../structures/task-memory.md | 2 - docs/griptape-framework/structures/tasks.md | 4 +- .../structures/workflows.md | 245 +++++++- docs/griptape-framework/tools/index.md | 2 +- griptape/chunkers/base_chunker.py | 5 + griptape/config/__init__.py | 2 + .../config/amazon_bedrock_structure_config.py | 7 +- griptape/config/cohere_structure_config.py | 37 ++ griptape/drivers/__init__.py | 42 +- .../amazon_bedrock_cohere_embedding_driver.py | 7 +- .../amazon_bedrock_titan_embedding_driver.py | 7 +- .../amazon_sagemaker_embedding_driver.py | 31 - ...on_sagemaker_jumpstart_embedding_driver.py | 53 ++ .../base_multi_model_embedding_driver.py | 15 - .../embedding/cohere_embedding_driver.py | 43 ++ .../base_embedding_model_driver.py | 11 - ...aker_huggingface_embedding_model_driver.py | 11 - ...r_tensorflow_hub_embedding_model_driver.py | 11 - .../prompt/amazon_bedrock_prompt_driver.py | 84 ++- ...mazon_sagemaker_jumpstart_prompt_driver.py | 94 +++ .../prompt/amazon_sagemaker_prompt_driver.py | 52 -- .../drivers/prompt/anthropic_prompt_driver.py | 32 +- .../azure_openai_completion_prompt_driver.py | 41 -- .../prompt/base_multi_model_prompt_driver.py | 38 -- griptape/drivers/prompt/base_prompt_driver.py | 33 +- .../drivers/prompt/cohere_prompt_driver.py | 50 +- .../drivers/prompt/dummy_prompt_driver.py | 3 + .../drivers/prompt/google_prompt_driver.py | 24 +- .../prompt/huggingface_hub_prompt_driver.py | 28 +- .../huggingface_pipeline_prompt_driver.py | 65 +- .../drivers/prompt/ollama_prompt_driver.py | 69 +++ .../prompt/openai_chat_prompt_driver.py | 81 +-- .../prompt/openai_completion_prompt_driver.py | 83 --- griptape/drivers/prompt_model/__init__.py | 0 .../prompt_model/base_prompt_model_driver.py | 29 - .../bedrock_claude_prompt_model_driver.py | 87 --- .../bedrock_jurassic_prompt_model_driver.py | 76 --- .../bedrock_llama_prompt_model_driver.py | 101 ---- .../bedrock_titan_prompt_model_driver.py | 83 --- .../sagemaker_falcon_prompt_model_driver.py | 42 -- .../sagemaker_llama_prompt_model_driver.py | 47 -- griptape/engines/query/vector_query_engine.py | 14 +- .../engines/summary/prompt_summary_engine.py | 32 +- griptape/loaders/web_loader.py | 7 +- .../structure/base_conversation_memory.py | 49 ++ griptape/schemas/base_schema.py | 5 +- griptape/structures/agent.py | 6 +- griptape/structures/pipeline.py | 8 +- griptape/structures/structure.py | 38 +- griptape/structures/workflow.py | 27 +- griptape/tasks/actions_subtask.py | 26 +- griptape/tasks/audio_transcription_task.py | 23 +- griptape/tasks/base_audio_generation_task.py | 11 +- griptape/tasks/base_audio_input_task.py | 38 ++ griptape/tasks/base_task.py | 28 + griptape/tasks/prompt_task.py | 2 +- griptape/tasks/toolkit_task.py | 14 +- .../engines/summary/prompt_summary.j2 | 27 - griptape/templates/engines/summary/system.j2 | 14 + griptape/templates/engines/summary/user.j2 | 5 + griptape/templates/tasks/tool_task/system.j2 | 3 +- griptape/tokenizers/__init__.py | 12 +- .../tokenizers/amazon_bedrock_tokenizer.py | 40 ++ griptape/tokenizers/anthropic_tokenizer.py | 7 +- griptape/tokenizers/base_tokenizer.py | 34 +- .../tokenizers/bedrock_claude_tokenizer.py | 12 - .../tokenizers/bedrock_cohere_tokenizer.py | 14 - .../tokenizers/bedrock_jurassic_tokenizer.py | 20 - .../tokenizers/bedrock_llama_tokenizer.py | 14 - .../tokenizers/bedrock_titan_tokenizer.py | 14 - griptape/tokenizers/cohere_tokenizer.py | 11 +- griptape/tokenizers/dummy_tokenizer.py | 5 +- griptape/tokenizers/google_tokenizer.py | 7 +- griptape/tokenizers/huggingface_tokenizer.py | 19 +- griptape/tokenizers/openai_tokenizer.py | 11 +- griptape/tokenizers/simple_tokenizer.py | 12 +- griptape/tokenizers/voyageai_tokenizer.py | 7 +- griptape/tools/__init__.py | 4 + .../tool.py | 14 +- griptape/tools/web_search/tool.py | 3 +- griptape/utils/__init__.py | 4 +- griptape/utils/constants.py | 4 - griptape/utils/prompt_stack.py | 51 -- griptape/utils/structure_visualizer.py | 42 ++ mkdocs.yml | 3 +- poetry.lock | 298 ++++----- pyproject.toml | 13 +- tests/mocks/mock_audio_input_task.py | 9 + tests/mocks/mock_prompt_driver.py | 11 +- tests/mocks/mock_tokenizer.py | 8 +- tests/unit/chunkers/test_text_chunker.py | 4 + .../test_amazon_bedrock_structure_config.py | 1 - .../config/test_anthropic_structure_config.py | 2 +- .../config/test_cohere_structure_config.py | 38 ++ .../embedding/test_cohere_embedding_driver.py | 21 + .../test_sagemaker_embedding_driver.py | 33 - ...st_sagemaker_jumpstart_embedding_driver.py | 59 ++ .../unit/drivers/embedding_model/__init__.py | 0 ...aker_huggingface_embedding_model_driver.py | 21 - ...r_tensorflow_hub_embedding_model_driver.py | 21 - .../test_amazon_bedrock_prompt_driver.py | 152 ++--- ...mazon_sagemaker_jumpstart_prompt_driver.py | 132 ++++ .../test_amazon_sagemaker_prompt_driver.py | 90 --- .../prompt/test_anthropic_prompt_driver.py | 8 +- .../test_azure_openai_chat_prompt_driver.py | 4 +- ...t_azure_openai_completion_prompt_driver.py | 75 --- .../drivers/prompt/test_base_prompt_driver.py | 29 - .../prompt/test_cohere_prompt_driver.py | 23 +- .../prompt/test_google_prompt_driver.py | 43 +- .../test_hugging_face_hub_prompt_driver.py | 7 + ...est_hugging_face_pipeline_prompt_driver.py | 32 +- .../prompt/test_ollama_prompt_driver.py | 96 +++ .../prompt/test_openai_chat_prompt_driver.py | 149 +---- .../test_openai_completion_prompt_driver.py | 112 ---- tests/unit/drivers/prompt_models/__init__.py | 0 ...test_bedrock_claude_prompt_model_driver.py | 129 ---- ...st_bedrock_jurassic_prompt_model_driver.py | 71 --- .../test_bedrock_llama_prompt_model_driver.py | 64 -- .../test_bedrock_titan_prompt_model_driver.py | 58 -- ...st_sagemaker_falcon_prompt_model_driver.py | 43 -- ...est_sagemaker_llama_prompt_model_driver.py | 67 --- .../test_local_structure_run_driver.py | 2 +- .../summary/test_prompt_summary_engine.py | 24 + tests/unit/loaders/test_web_loader.py | 19 +- .../structure/test_conversation_memory.py | 97 +++ tests/unit/structures/test_agent.py | 10 + tests/unit/structures/test_workflow.py | 564 +++++++++++++++--- .../tasks/test_audio_transcription_task.py | 19 +- .../unit/tasks/test_base_audio_input_task.py | 26 + tests/unit/tasks/test_base_task.py | 38 ++ tests/unit/tasks/test_text_to_speech_task.py | 21 +- .../unit/tokenizers}/__init__.py | 0 ...er.py => test_amazon_bedrock_tokenizer.py} | 30 +- tests/unit/tokenizers/test_base_tokenizer.py | 13 + .../test_bedrock_cohere_tokenizer.py | 25 - .../test_bedrock_jurassic_tokenizer.py | 39 -- .../test_bedrock_llama_tokenizer.py | 35 -- .../test_bedrock_titan_tokenizer.py | 31 - .../unit/tokenizers/test_cohere_tokenizer.py | 1 + .../unit/tokenizers/test_google_tokenizer.py | 2 + .../tokenizers/test_hugging_face_tokenizer.py | 7 +- .../unit/tokenizers/test_openai_tokenizer.py | 12 + ...st_griptape_cloud_knowledge_base_client.py | 57 +- tests/unit/tools/test_web_search.py | 33 +- tests/unit/utils/test_prompt_stack.py | 98 --- tests/unit/utils/test_structure_visualizer.py | 52 ++ tests/utils/structure_tester.py | 132 ++-- 175 files changed, 3122 insertions(+), 3502 deletions(-) delete mode 100644 docs/griptape-framework/engines/image-query-engines.md create mode 100644 griptape/config/cohere_structure_config.py delete mode 100644 griptape/drivers/embedding/amazon_sagemaker_embedding_driver.py create mode 100644 griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py delete mode 100644 griptape/drivers/embedding/base_multi_model_embedding_driver.py create mode 100644 griptape/drivers/embedding/cohere_embedding_driver.py delete mode 100644 griptape/drivers/embedding_model/base_embedding_model_driver.py delete mode 100644 griptape/drivers/embedding_model/sagemaker_huggingface_embedding_model_driver.py delete mode 100644 griptape/drivers/embedding_model/sagemaker_tensorflow_hub_embedding_model_driver.py create mode 100644 griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py delete mode 100644 griptape/drivers/prompt/amazon_sagemaker_prompt_driver.py delete mode 100644 griptape/drivers/prompt/azure_openai_completion_prompt_driver.py delete mode 100644 griptape/drivers/prompt/base_multi_model_prompt_driver.py create mode 100644 griptape/drivers/prompt/ollama_prompt_driver.py delete mode 100644 griptape/drivers/prompt/openai_completion_prompt_driver.py delete mode 100644 griptape/drivers/prompt_model/__init__.py delete mode 100644 griptape/drivers/prompt_model/base_prompt_model_driver.py delete mode 100644 griptape/drivers/prompt_model/bedrock_claude_prompt_model_driver.py delete mode 100644 griptape/drivers/prompt_model/bedrock_jurassic_prompt_model_driver.py delete mode 100644 griptape/drivers/prompt_model/bedrock_llama_prompt_model_driver.py delete mode 100644 griptape/drivers/prompt_model/bedrock_titan_prompt_model_driver.py delete mode 100644 griptape/drivers/prompt_model/sagemaker_falcon_prompt_model_driver.py delete mode 100644 griptape/drivers/prompt_model/sagemaker_llama_prompt_model_driver.py create mode 100644 griptape/tasks/base_audio_input_task.py delete mode 100644 griptape/templates/engines/summary/prompt_summary.j2 create mode 100644 griptape/templates/engines/summary/system.j2 create mode 100644 griptape/templates/engines/summary/user.j2 create mode 100644 griptape/tokenizers/amazon_bedrock_tokenizer.py delete mode 100644 griptape/tokenizers/bedrock_claude_tokenizer.py delete mode 100644 griptape/tokenizers/bedrock_cohere_tokenizer.py delete mode 100644 griptape/tokenizers/bedrock_jurassic_tokenizer.py delete mode 100644 griptape/tokenizers/bedrock_llama_tokenizer.py delete mode 100644 griptape/tokenizers/bedrock_titan_tokenizer.py create mode 100644 griptape/utils/structure_visualizer.py create mode 100644 tests/mocks/mock_audio_input_task.py create mode 100644 tests/unit/config/test_cohere_structure_config.py create mode 100644 tests/unit/drivers/embedding/test_cohere_embedding_driver.py delete mode 100644 tests/unit/drivers/embedding/test_sagemaker_embedding_driver.py create mode 100644 tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py delete mode 100644 tests/unit/drivers/embedding_model/__init__.py delete mode 100644 tests/unit/drivers/embedding_model/test_sagemaker_huggingface_embedding_model_driver.py delete mode 100644 tests/unit/drivers/embedding_model/test_sagemaker_tensorflow_hub_embedding_model_driver.py create mode 100644 tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py delete mode 100644 tests/unit/drivers/prompt/test_amazon_sagemaker_prompt_driver.py delete mode 100644 tests/unit/drivers/prompt/test_azure_openai_completion_prompt_driver.py create mode 100644 tests/unit/drivers/prompt/test_ollama_prompt_driver.py delete mode 100644 tests/unit/drivers/prompt/test_openai_completion_prompt_driver.py delete mode 100644 tests/unit/drivers/prompt_models/__init__.py delete mode 100644 tests/unit/drivers/prompt_models/test_bedrock_claude_prompt_model_driver.py delete mode 100644 tests/unit/drivers/prompt_models/test_bedrock_jurassic_prompt_model_driver.py delete mode 100644 tests/unit/drivers/prompt_models/test_bedrock_llama_prompt_model_driver.py delete mode 100644 tests/unit/drivers/prompt_models/test_bedrock_titan_prompt_model_driver.py delete mode 100644 tests/unit/drivers/prompt_models/test_sagemaker_falcon_prompt_model_driver.py delete mode 100644 tests/unit/drivers/prompt_models/test_sagemaker_llama_prompt_model_driver.py create mode 100644 tests/unit/tasks/test_base_audio_input_task.py rename {griptape/drivers/embedding_model => tests/unit/tokenizers}/__init__.py (100%) rename tests/unit/tokenizers/{test_bedrock_claude_tokenizer.py => test_amazon_bedrock_tokenizer.py} (51%) create mode 100644 tests/unit/tokenizers/test_base_tokenizer.py delete mode 100644 tests/unit/tokenizers/test_bedrock_cohere_tokenizer.py delete mode 100644 tests/unit/tokenizers/test_bedrock_jurassic_tokenizer.py delete mode 100644 tests/unit/tokenizers/test_bedrock_llama_tokenizer.py delete mode 100644 tests/unit/tokenizers/test_bedrock_titan_tokenizer.py create mode 100644 tests/unit/utils/test_structure_visualizer.py diff --git a/.coveragerc b/.coveragerc index a55d8962f..6112755cc 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,28 +1,15 @@ [run] -data_file = coverage/.coverage branch = True [report] -; Regexes for lines to exclude from consideration exclude_also = - ; Don't complain about missing debug-only code: - def __repr__ - if self\.debug - - ; Don't complain if tests don't hit defensive assertion code: - raise AssertionError - raise NotImplementedError - - ; Don't complain if non-runnable code isn't run: - if 0: - if __name__ == .__main__.: - if TYPE_CHECKING: - - ; Don't complain about abstract methods, they aren't run: - @(abc\.)?abstractmethod - -[html] -directory = coverage/html - -[xml] -output = coverage/coverage.xml + def __repr__ + if self.debug: + if settings.DEBUG + raise AssertionError + raise NotImplementedError + if 0: + if __name__ == .__main__.: + if TYPE_CHECKING: + class .*\bProtocol\): + @(abc\.)?abstractmethod diff --git a/.gitignore b/.gitignore index ba63b4aca..c71d930a9 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ __pycache__ npm-debug.log **/.mypy_cache/** !yarn.lock -coverage/ cucumber-report.json **/.vscode-test/** **/.vscode test/** @@ -57,3 +56,7 @@ dist/** # mkdocs build output site reference + +# coverage.py +htmlcov/ +coverage.* diff --git a/CHANGELOG.md b/CHANGELOG.md index d7698127a..bf9ea5b22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,77 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.27.0] - 2024-06-19 + +### Added +- `BaseTask.add_child()` to add a child task to a parent task. +- `BaseTask.add_children()` to add multiple child tasks to a parent task. +- `BaseTask.add_parent()` to add a parent task to a child task. +- `BaseTask.add_parents()` to add multiple parent tasks to a child task. +- `Structure.resolve_relationships()` to resolve asymmetrically defined parent/child relationships. In other words, if a parent declares a child, but the child does not declare the parent, the parent will automatically be added as a parent of the child when running this method. The method is invoked automatically by `Structure.before_run()`. +- `CohereEmbeddingDriver` for using Cohere's embeddings API. +- `CohereStructureConfig` for providing Structures with quick Cohere configuration. +- `AmazonSageMakerJumpstartPromptDriver.inference_component_name` for setting the `InferenceComponentName` parameter when invoking an endpoint. +- `AmazonSageMakerJumpstartEmbeddingDriver.inference_component_name` for setting the `InferenceComponentName` parameter when invoking an endpoint. +- `AmazonSageMakerJumpstartEmbeddingDriver.custom_attributes` for setting custom attributes when invoking an endpoint. +- `ToolkitTask.response_stop_sequence` for overriding the default Chain of Thought stop sequence. +- `griptape.utils.StructureVisualizer` for visualizing Workflow structures with Mermaid.js +- `BaseTask.parents_outputs` to get the textual output of all parent tasks. +- `BaseTask.parents_output_text` to get a concatenated string of all parent tasks' outputs. +- `parents_output_text` to Workflow context. +- `OllamaPromptModelDriver` for using models with Ollama. +- Parameter `output` on `Structure` as a convenience for `output_task.output` + +### Changed +- **BREAKING**: `Workflow` no longer modifies task relationships when adding tasks via `tasks` init param, `add_tasks()` or `add_task()`. Previously, adding a task would automatically add the previously added task as its parent. Existing code that relies on this behavior will need to be updated to explicitly add parent/child relationships using the API offered by `BaseTask`. +- **BREAKING**: Removed `AmazonBedrockPromptDriver.prompt_model_driver` as it is no longer needed with the `AmazonBedrockPromptDriver` Converse API implementation. +- **BREAKING**: Removed `BedrockClaudePromptModelDriver`. +- **BREAKING**: Removed `BedrockJurassicPromptModelDriver`. +- **BREAKING**: Removed `BedrockLlamaPromptModelDriver`. +- **BREAKING**: Removed `BedrockTitanPromptModelDriver`. +- **BREAKING**: Removed `BedrockClaudeTokenizer`, use `SimpleTokenizer` instead. +- **BREAKING**: Removed `BedrockJurassicTokenizer`, use `SimpleTokenizer` instead. +- **BREAKING**: Removed `BedrockLlamaTokenizer`, use `SimpleTokenizer` instead. +- **BREAKING**: Removed `BedrockTitanTokenizer`, use `SimpleTokenizer` instead. +- **BREAKING**: Removed `OpenAiChatCompletionPromptDriver` as it uses the legacy [OpenAi Completions API](https://platform.openai.com/docs/api-reference/completions). +- **BREAKING**: Removed `BasePromptDriver.count_tokens()`. +- **BREAKING**: Removed `BasePromptDriver.max_output_tokens()`. +- **BREAKING**: Moved/renamed `PromptStack.add_to_conversation_memory` to `BaseConversationMemory.add_to_prompt_stack`. +- **BREAKING**: Moved `griptape.constants.RESPONSE_STOP_SEQUENCE` to `ToolkitTask`. +- **BREAKING**: Renamed `AmazonSagemakerPromptDriver` to `AmazonSageMakerJumpstartPromptDriver`. +- **BREAKING**: Removed `SagemakerFalconPromptModelDriver`, use `AmazonSageMakerJumpstartPromptDriver` instead. +- **BREAKING**: Removed `SagemakerLlamaPromptModelDriver`, use `AmazonSageMakerJumpstartPromptDriver` instead. +- **BREAKING**: Renamed `AmazonSagemakerEmbeddingDriver` to `AmazonSageMakerJumpstartEmbeddingDriver`. +- **BREAKING**: Removed `SagemakerHuggingfaceEmbeddingModelDriver`, use `AmazonSageMakerJumpstartEmbeddingDriver` instead. +- **BREAKING**: Removed `SagemakerTensorflowHubEmbeddingModelDriver`, use `AmazonSageMakerJumpstartEmbeddingDriver` instead. +- **BREAKING**: `AmazonSageMakerJumpstartPromptDriver.model` parameter, which gets passed to `SageMakerRuntime.Client.invoke_endpoint` as `EndpointName`, is now renamed to `AmazonSageMakerPromptDriver.endpoint`. +- **BREAKING**: Removed parameter `template_generator` on `PromptSummaryEngine` and added parameters `system_template_generator` and `user_template_generator`. +- **BREAKING**: Removed template `engines/summary/prompt_summary.j2` and added templates `engines/summary/system.j2` and `engines/summary/user.j2`. +- `ToolkitTask.RESPONSE_STOP_SEQUENCE` is now only added when using `ToolkitTask`. +- Updated Prompt Drivers to use `BasePromptDriver.max_tokens` instead of using `BasePromptDriver.max_output_tokens()`. +- Improved error message when `GriptapeCloudKnowledgeBaseClient` does not have a description set. +- Updated `AmazonBedrockPromptDriver` to use [Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html). +- `Structure.before_run()` now automatically resolves asymmetrically defined parent/child relationships using the new `Structure.resolve_relationships()`. +- Updated `HuggingFaceHubPromptDriver` to use `transformers`'s `apply_chat_template`. +- Updated `HuggingFacePipelinePromptDriver` to use chat features of `transformers.TextGenerationPipeline`. +- Updated `CoherePromptDriver` to use Cohere's latest SDK. +- Moved Task reset logic for all Structures to `Structure.before_run`. +- Updated default prompt templates for `PromptSummaryEngine`. +- Updated template `templates/tasks/tool_task/system.j2`. + +### Fixed +- `Workflow.insert_task()` no longer inserts duplicate tasks when given multiple parent tasks. +- Performance issue in `OpenAiChatPromptDriver` when extracting unused rate-limiting headers. +- Streaming not working when using deprecated `Structure.stream` field. +- Raw Tool output being lost when being executed by ActionsSubtask. +- Re-order Workflow tasks on every task execution wave. +- Web Loader to catch Exceptions and properly return an ErrorArtifact. +- Conversation Memory entry only added if `output_task.output` is not `None` on all `Structures` +- `TextArtifacts` contained in `ListArtifact` returned by `WebSearch.search` to properly formatted stringified JSON. +- Structure run args not being set immediately. +- Input and output logging in BaseAudioInputTasks and BaseAudioGenerationTasks +- Validation of `max_tokens` < 0 on `BaseChunker` + ## [0.26.0] - 2024-06-04 ### Added @@ -15,7 +86,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `AudioTranscriptionTask` and `AudioTranscriptionClient` for transcribing audio content in Structures. - `OpenAiAudioTranscriptionDriver` for integration with OpenAI's speech-to-text models, including Whisper. - Parameter `env` to `BaseStructureRunDriver` to set environment variables for a Structure Run. -- `PusherEventListenerDriver` to enable sending of framework events over a Pusher WebSocket. +- `PusherEventListenerDriver` to enable sending of framework events over a Pusher WebSocket. ### Changed - **BREAKING**: Removed `StructureConfig.global_drivers`. Pass Drivers directly to the Structure Config instead. diff --git a/Makefile b/Makefile index 61d91e6a1..b4f3d0068 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ version: ## Bump version and push to release branch. .PHONY: publish publish: ## Push git tag and publish version to PyPI. - @git tag v$$(poetry version -s) + @git tag $$(poetry version -s) @git push --tags @poetry build @poetry publish diff --git a/docs/examples/amazon-dynamodb-sessions.md b/docs/examples/amazon-dynamodb-sessions.md index 279cced2a..aa4050ab9 100644 --- a/docs/examples/amazon-dynamodb-sessions.md +++ b/docs/examples/amazon-dynamodb-sessions.md @@ -1,8 +1,8 @@ Griptape provides [Conversation Memory](../griptape-framework/structures/conversation-memory.md) as a means of persisting conversation context across multiple Structure runs. If you provide it with a suitable Driver, the memory of the previous conversation can be preserved between run of a Structure, giving it additional context for how to respond. -While we can use the [LocalConversationMemoryDriver](../griptape-framework/drivers/conversation-memory-drivers.md#localconversationmemorydriver) to store the conversation history in a local file, this may not be suitable for production use cases. +While we can use the [LocalConversationMemoryDriver](../griptape-framework/drivers/conversation-memory-drivers.md#local) to store the conversation history in a local file, in production use-cases we may want to store in a proper database. -In this example, we will show you how to use the [AmazonDynamoDbConversationMemoryDriver](../griptape-framework/drivers/conversation-memory-drivers.md#amazondynamodbconversationmemorydriver) to persist the memory in an [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) table. Please refer to the [Amazon DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-1.html) for information on setting up DynamoDB. +In this example, we will show you how to use the [AmazonDynamoDbConversationMemoryDriver](../griptape-framework/drivers/conversation-memory-drivers.md#amazon-dynamodb) to persist the memory in an [Amazon DynamoDB](https://aws.amazon.com/dynamodb/) table. Please refer to the [Amazon DynamoDB documentation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-1.html) for information on setting up DynamoDB. This code implements the idea of a generic "Session" that represents a Conversation Memory entry. For example, a "Session" could be used to represent an individual user's conversation, or a group conversation thread. diff --git a/docs/examples/multi-agent-workflow.md b/docs/examples/multi-agent-workflow.md index 044f4abad..d0fa65232 100644 --- a/docs/examples/multi-agent-workflow.md +++ b/docs/examples/multi-agent-workflow.md @@ -1,7 +1,7 @@ In this example we implement a multi-agent Workflow. We have a single "Researcher" Agent that conducts research on a topic, and then fans out to multiple "Writer" Agents to write blog posts based on the research. By splitting up our workloads across multiple Structures, we can parallelize the work and leverage the strengths of each Agent. The Researcher can focus on gathering data and insights, while the Writers can focus on crafting engaging narratives. -Additionally, this architecture opens us up to using services such as [Griptape Cloud](https://www.griptape.ai/cloud) to have each Agent run on a separate machine, allowing us to scale our Workflow as needed 🤯. +Additionally, this architecture opens us up to using services such as [Griptape Cloud](https://www.griptape.ai/cloud) to have each Agent run completely independently, allowing us to scale our Workflow as needed 🤯. To try out how this would work, you can deploy this example as multiple structures from our [Sample Structures](https://github.com/griptape-ai/griptape-sample-structures/tree/main/griptape-multi-agent-workflows) repo. ```python @@ -155,35 +155,33 @@ if __name__ == "__main__": ), ), ) - end_task = team.add_task( - PromptTask( - 'State "All Done!"', - ) - ) - team.insert_tasks( - research_task, - [ - StructureRunTask( - ( - """Using insights provided, develop an engaging blog + writer_tasks = team.add_tasks(*[ + StructureRunTask( + ( + """Using insights provided, develop an engaging blog post that highlights the most significant AI advancements. Your post should be informative yet accessible, catering to a tech-savvy audience. Make it sound cool, avoid complex words so it doesn't sound like AI. Insights: {{ parent_outputs["research"] }}""", - ), - driver=LocalStructureRunDriver( - structure_factory_fn=lambda: build_writer( - role=writer["role"], - goal=writer["goal"], - backstory=writer["backstory"], - ) - ), - ) - for writer in WRITERS - ], - end_task, + ), + driver=LocalStructureRunDriver( + structure_factory_fn=lambda: build_writer( + role=writer["role"], + goal=writer["goal"], + backstory=writer["backstory"], + ) + ), + parent_ids=[research_task.id], + ) + for writer in WRITERS + ]) + end_task = team.add_task( + PromptTask( + 'State "All Done!"', + parent_ids=[writer_task.id for writer_task in writer_tasks], + ) ) team.run() diff --git a/docs/griptape-framework/data/artifacts.md b/docs/griptape-framework/data/artifacts.md index 18d5cb61f..5b69b120a 100644 --- a/docs/griptape-framework/data/artifacts.md +++ b/docs/griptape-framework/data/artifacts.md @@ -14,7 +14,7 @@ and access it with [embedding](../../reference/griptape/artifacts/text_artifact. ## CsvRowArtifact Used for passing structured row data around the framework. It inherits from [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) and overrides the -[to_text()](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.to_text) method, which always returns a valid CSV row. +[to_text()](../../reference/griptape/artifacts/csv_row_artifact.md#griptape.artifacts.csv_row_artifact.CsvRowArtifact.to_text) method, which always returns a valid CSV row. ## InfoArtifact @@ -29,7 +29,7 @@ Used for passing errors back to the LLM without task memory storing them. Used for passing binary large objects (blobs) back to the LLM. Treat it as a way to return unstructured data, such as images, videos, audio, and other files back from tools. Each blob has a [name](../../reference/griptape/artifacts/base_artifact.md#griptape.artifacts.base_artifact.BaseArtifact.name) and -[dir](../../reference/griptape/artifacts/blob_artifact.md#griptape.artifacts.blob_artifact.BlobArtifact.dir) to uniquely identify stored objects. +[dir](../../reference/griptape/artifacts/blob_artifact.md#griptape.artifacts.blob_artifact.BlobArtifact.dir_name) to uniquely identify stored objects. [TaskMemory](../../reference/griptape/memory/task/task_memory.md) automatically stores [BlobArtifact](../../reference/griptape/artifacts/blob_artifact.md)s returned by tool activities that can be reused by other tools. diff --git a/docs/griptape-framework/data/loaders.md b/docs/griptape-framework/data/loaders.md index 69ffeda06..dbc578ccd 100644 --- a/docs/griptape-framework/data/loaders.md +++ b/docs/griptape-framework/data/loaders.md @@ -4,7 +4,7 @@ Loaders are used to load textual data from different sources and chunk it into [ Each loader can be used to load a single "document" with [load()](../../reference/griptape/loaders/base_loader.md#griptape.loaders.base_loader.BaseLoader.load) or multiple documents with [load_collection()](../../reference/griptape/loaders/base_loader.md#griptape.loaders.base_loader.BaseLoader.load_collection). -## Pdf Loader +## PDF !!! info This driver requires the `loaders-pdf` [extra](../index.md#extras). @@ -33,7 +33,7 @@ with open("attention.pdf", "rb") as attention, open("CoT.pdf", "rb") as cot: PdfLoader().load_collection(list(load_files(["attention.pdf", "CoT.pdf"]).values())) ``` -## Sql Loader +## SQL Can be used to load data from a SQL database into [CsvRowArtifact](../../reference/griptape/artifacts/csv_row_artifact.md)s: @@ -54,7 +54,7 @@ SqlLoader( ).load_collection(["SELECT 'foo', 'bar';", "SELECT 'fizz', 'buzz';"]) ``` -## Csv Loader +## CSV Can be used to load CSV files into [CsvRowArtifact](../../reference/griptape/artifacts/csv_row_artifact.md)s: @@ -76,7 +76,7 @@ CsvLoader().load_collection(list(load_files(["tests/resources/cities.csv", "test ``` -## DataFrame Loader +## DataFrame !!! info This driver requires the `loaders-dataframe` [extra](../index.md#extras). @@ -100,7 +100,7 @@ DataFrameLoader().load_collection( ``` -## Text Loader +## Text Used to load arbitrary text and text files: @@ -124,9 +124,9 @@ with open("example.txt", "r") as f: ) ``` -You can set a custom [tokenizer](../../reference/griptape/loaders/text_loader.md#griptape.loaders.text_loader.TextLoader.tokenizer.md), [max_tokens](../../reference/griptape/loaders/text_loader.md#griptape.loaders.text_loader.TextLoader.max_tokens.md) parameter, and [chunker](../../reference/griptape/loaders/text_loader.md#griptape.loaders.text_loader.TextLoader.chunker.md). +You can set a custom [tokenizer](../../reference/griptape/loaders/text_loader.md#griptape.loaders.text_loader.TextLoader.tokenizer), [max_tokens](../../reference/griptape/loaders/text_loader.md#griptape.loaders.text_loader.TextLoader.max_tokens) parameter, and [chunker](../../reference/griptape/loaders/text_loader.md#griptape.loaders.text_loader.TextLoader.chunker). -## Web Loader +## Web !!! info This driver requires the `loaders-web` [extra](../index.md#extras). @@ -145,7 +145,7 @@ WebLoader().load_collection( ) ``` -## Image Loader +## Image !!! info This driver requires the `loaders-image` [extra](../index.md#extras). @@ -183,7 +183,7 @@ ImageLoader().load_collection(list(load_files(["tests/resources/mountain.png", " ``` -## Email Loader +## Email !!! info This driver requires the `loaders-email` [extra](../index.md#extras). @@ -200,7 +200,7 @@ loader.load(EmailLoader.EmailQuery(label="INBOX")) loader.load_collection([EmailLoader.EmailQuery(label="INBOX"), EmailLoader.EmailQuery(label="SENT")]) ``` -## Audio Loader +## Audio !!! info This driver requires the `loaders-audio` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/conversation-memory-drivers.md b/docs/griptape-framework/drivers/conversation-memory-drivers.md index 4c3de1e65..2ca5f8dd3 100644 --- a/docs/griptape-framework/drivers/conversation-memory-drivers.md +++ b/docs/griptape-framework/drivers/conversation-memory-drivers.md @@ -2,7 +2,7 @@ You can persist and load memory by using Conversation Memory Drivers. You can build drivers for your own data stores by extending [BaseConversationMemoryDriver](../../reference/griptape/drivers/memory/conversation/base_conversation_memory_driver.md). -### LocalConversationMemoryDriver +### Local The [LocalConversationMemoryDriver](../../reference/griptape/drivers/memory/conversation/local_conversation_memory_driver.md) allows you to persist Conversation Memory in a local JSON file. @@ -18,7 +18,7 @@ agent.run("Surfing is my favorite sport.") agent.run("What is my favorite sport?") ``` -### AmazonDynamoDbConversationMemoryDriver +### Amazon DynamoDb !!! info This driver requires the `drivers-memory-conversation-amazon-dynamodb` [extra](../index.md#extras). @@ -47,7 +47,7 @@ agent.run("What is my name?") ``` -### Redis Conversation Memory Driver +### Redis !!! info This driver requires the `drivers-memory-conversation-redis` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/embedding-drivers.md b/docs/griptape-framework/drivers/embedding-drivers.md index 49dfde4a5..3f0135ac3 100644 --- a/docs/griptape-framework/drivers/embedding-drivers.md +++ b/docs/griptape-framework/drivers/embedding-drivers.md @@ -10,7 +10,7 @@ You can optionally provide a [Tokenizer](../misc/tokenizers.md) via the [tokeniz ## Embedding Drivers -### OpenAI Embeddings +### OpenAI The [OpenAiEmbeddingDriver](../../reference/griptape/drivers/embedding/openai_embedding_driver.md) uses the [OpenAI Embeddings API](https://platform.openai.com/docs/guides/embeddings). @@ -27,12 +27,12 @@ print(embeddings[:3]) [0.0017853748286142945, 0.006118456833064556, -0.005811543669551611] ``` -### Azure OpenAI Embeddings +### Azure OpenAI The [AzureOpenAiEmbeddingDriver](../../reference/griptape/drivers/embedding/azure_openai_embedding_driver.md) uses the same parameters as [OpenAiEmbeddingDriver](../../reference/griptape/drivers/embedding/openai_embedding_driver.md) with updated defaults. -### Bedrock Titan Embeddings +### Bedrock Titan !!! info This driver requires the `drivers-embedding-amazon-bedrock` [extra](../index.md#extras). @@ -51,7 +51,7 @@ print(embeddings[:3]) [-0.234375, -0.024902344, -0.14941406] ``` -### Google Embeddings +### Google !!! info This driver requires the `drivers-embedding-google` [extra](../index.md#extras). @@ -69,7 +69,7 @@ print(embeddings[:3]) [0.0588633, 0.0033929371, -0.072810836] ``` -### Hugging Face Hub Embeddings +### Hugging Face Hub !!! info This driver requires the `drivers-embedding-huggingface` [extra](../index.md#extras). @@ -88,10 +88,8 @@ driver = HuggingFaceHubEmbeddingDriver( api_token=os.environ["HUGGINGFACE_HUB_ACCESS_TOKEN"], model="sentence-transformers/all-MiniLM-L6-v2", tokenizer=HuggingFaceTokenizer( + model="sentence-transformers/all-MiniLM-L6-v2", max_output_tokens=512, - tokenizer=AutoTokenizer.from_pretrained( - "sentence-transformers/all-MiniLM-L6-v2" - ) ), ) @@ -99,27 +97,21 @@ embeddings = driver.embed_string("Hello world!") # display the first 3 embeddings print(embeddings[:3]) -``` -### Multi Model Embedding Drivers -Certain embeddings providers such as Amazon SageMaker support many types of models, each with their own slight differences in parameters and response formats. To support this variation across models, these Embedding Drivers takes a [Embedding Model Driver](../../reference/griptape/drivers/embedding_model/base_embedding_model_driver.md) -through the [embedding_model_driver](../../reference/griptape/drivers/embedding/base_multi_model_embedding_driver.md#griptape.drivers.embedding.base_multi_model_embedding_driver.BaseMultiModelEmbeddingDriver.embedding_model_driver) parameter. -[Embedding Model Driver](../../reference/griptape/drivers/embedding_model/base_embedding_model_driver.md)s allows for model-specific customization for Embedding Drivers. -#### SageMaker Embeddings +``` +### Amazon SageMaker Jumpstart -The [AmazonSageMakerEmbeddingDriver](../../reference/griptape/drivers/embedding/amazon_sagemaker_embedding_driver.md) uses the [Amazon SageMaker Endpoints](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html) to generate embeddings on AWS. +The [AmazonSageMakerJumpstartEmbeddingDriver](../../reference/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.md) uses the [Amazon SageMaker Endpoints](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html) to generate embeddings on AWS. !!! info This driver requires the `drivers-embedding-amazon-sagemaker` [extra](../index.md#extras). -##### TensorFlow Hub Models ```python title="PYTEST_IGNORE" import os -from griptape.drivers import AmazonSageMakerEmbeddingDriver, SageMakerTensorFlowHubEmbeddingModelDriver +from griptape.drivers import AmazonSageMakerJumpstartEmbeddingDriver, SageMakerTensorFlowHubEmbeddingModelDriver -driver = AmazonSageMakerEmbeddingDriver( +driver = AmazonSageMakerJumpstartEmbeddingDriver( model=os.environ["SAGEMAKER_TENSORFLOW_HUB_MODEL"], - embedding_model_driver=SageMakerTensorFlowHubEmbeddingModelDriver(), ) embeddings = driver.embed_string("Hello world!") @@ -128,14 +120,18 @@ embeddings = driver.embed_string("Hello world!") print(embeddings[:3]) ``` -##### HuggingFace Models -```python title="PYTEST_IGNORE" +### VoyageAI +The [VoyageAiEmbeddingDriver](../../reference/griptape/drivers/embedding/voyageai_embedding_driver.md) uses the [VoyageAI Embeddings API](https://www.voyageai.com/). + +!!! info + This driver requires the `drivers-embedding-voyageai` [extra](../index.md#extras). + +```python import os -from griptape.drivers import AmazonSageMakerEmbeddingDriver, SageMakerHuggingFaceEmbeddingModelDriver +from griptape.drivers import VoyageAiEmbeddingDriver -driver = AmazonSageMakerEmbeddingDriver( - model=os.environ["SAGEMAKER_HUGGINGFACE_MODEL"], - embedding_model_driver=SageMakerHuggingFaceEmbeddingModelDriver(), +driver = VoyageAiEmbeddingDriver( + api_key=os.environ["VOYAGE_API_KEY"] ) embeddings = driver.embed_string("Hello world!") @@ -144,21 +140,24 @@ embeddings = driver.embed_string("Hello world!") print(embeddings[:3]) ``` -### VoyageAI Embeddings -The [VoyageAiEmbeddingDriver](../../reference/griptape/drivers/embedding/voyageai_embedding_driver.md) uses the [VoyageAI Embeddings API](https://www.voyageai.com/). +### Cohere + +The [CohereEmbeddingDriver](../../reference/griptape/drivers/embedding/cohere_embedding_driver.md) uses the [Cohere Embeddings API](https://docs.cohere.com/docs/embeddings). !!! info - This driver requires the `drivers-embedding-voyageai` [extra](../index.md#extras). + This driver requires the `drivers-embedding-cohere` [extra](../index.md#extras). ```python import os -from griptape.drivers import VoyageAiEmbeddingDriver +from griptape.drivers import CohereEmbeddingDriver -driver = VoyageAiEmbeddingDriver( - api_key=os.environ["VOYAGE_API_KEY"] +embedding_driver=CohereEmbeddingDriver( + model="embed-english-v3.0", + api_key=os.environ["COHERE_API_KEY"], + input_type="search_document", ) -embeddings = driver.embed_string("Hello world!") +embeddings = embedding_driver.embed_string("Hello world!") # display the first 3 embeddings print(embeddings[:3]) diff --git a/docs/griptape-framework/drivers/event-listener-drivers.md b/docs/griptape-framework/drivers/event-listener-drivers.md index 6e8f59b22..4a85bc9a4 100644 --- a/docs/griptape-framework/drivers/event-listener-drivers.md +++ b/docs/griptape-framework/drivers/event-listener-drivers.md @@ -66,7 +66,7 @@ event_driver.publish_event(done_event) Griptape offers the following Event Listener Drivers for forwarding Griptape Events. -### Amazon SQS Event Listener Driver +### Amazon SQS !!! info This driver requires the `drivers-event-listener-amazon-sqs` [extra](../index.md#extras). @@ -108,7 +108,7 @@ agent.run( ) ``` -### AWS IoT Event Listener Driver +### AWS IoT !!! info This driver requires the `drivers-event-listener-amazon-iot` [extra](../index.md#extras). @@ -152,7 +152,7 @@ agent = Agent( agent.run("I want to fly from Orlando to Boston") ``` -### Griptape Cloud Event Listener Driver +### Griptape Cloud The [GriptapeCloudEventListenerDriver](../../reference/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.md) sends Events to [Griptape Cloud](https://www.griptape.ai/cloud). @@ -212,7 +212,7 @@ agent = Agent( agent.run("Analyze the pros and cons of remote work vs. office work") ``` -### Pusher Event Listener Driver +### Pusher !!! info This driver requires the `drivers-event-listener-pusher` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/image-generation-drivers.md b/docs/griptape-framework/drivers/image-generation-drivers.md index 7389ff711..25572ba9c 100644 --- a/docs/griptape-framework/drivers/image-generation-drivers.md +++ b/docs/griptape-framework/drivers/image-generation-drivers.md @@ -27,7 +27,7 @@ agent.run("Generate a watercolor painting of a dog riding a skateboard") The [Amazon Bedrock Image Generation Driver](../../reference/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.md) provides multi-model access to image generation models hosted by Amazon Bedrock. This Driver manages API calls to the Bedrock API, while the specific Model Drivers below format the API requests and parse the responses. -#### Bedrock Stable Diffusion Model Driver +#### Stable Diffusion The [Bedrock Stable Diffusion Model Driver](../../reference/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.md) provides support for Stable Diffusion models hosted by Amazon Bedrock. This Model Driver supports configurations specific to Stable Diffusion, like style presets, clip guidance presets, and sampler. @@ -58,7 +58,7 @@ agent = Agent(tools=[ agent.run("Generate an image of a dog riding a skateboard") ``` -#### Bedrock Titan Image Generator Model Driver +#### Titan The [Bedrock Titan Image Generator Model Driver](../../reference/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.md) provides support for Titan Image Generator models hosted by Amazon Bedrock. This Model Driver supports configurations specific to Titan Image Generator, like quality, seed, and cfg_scale. diff --git a/docs/griptape-framework/drivers/image-query-drivers.md b/docs/griptape-framework/drivers/image-query-drivers.md index d795838d4..8003924b1 100644 --- a/docs/griptape-framework/drivers/image-query-drivers.md +++ b/docs/griptape-framework/drivers/image-query-drivers.md @@ -1,11 +1,11 @@ # Image Query Drivers -Image Query Drivers are used by [Image Query Engines](../engines/image-query-engines.md) to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular Image Query Driver. +Image Query Drivers are used by [Image Query Engines](../engines/query-engines.md#image) to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular Image Query Driver. !!! info All Image Query Drivers default to a `max_tokens` of 256. It is recommended that you set this value to correspond to the desired response length. -## AnthropicImageQueryDriver +## Anthropic !!! info To tune `max_tokens`, see [Anthropic's documentation on image tokens](https://docs.anthropic.com/claude/docs/vision#image-costs) for more information on how to relate token count to response length. @@ -59,7 +59,7 @@ result = engine.run("Describe the weather in the image", [image_artifact1, image print(result) ``` -## OpenAiVisionImageQueryDriver +## OpenAI !!! info While the `max_tokens` field is optional, it is recommended to set this to a value that corresponds to the desired response length. Without an explicit value, the model will default to very short responses. See [OpenAI's documentation](https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them) for more information on how to relate token count to response length. @@ -86,7 +86,7 @@ with open("tests/resources/mountain.png", "rb") as f: engine.run("Describe the weather in the image", [image_artifact]) ``` -## AzureOpenAiVisionImageQueryDriver +## Azure OpenAI !!! info In order to use the `gpt-4-vision-preview` model on Azure OpenAI, the `gpt-4` model must be deployed with the version set to `vision-preview`. More information can be found in the [Azure OpenAI documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/gpt-with-vision). @@ -117,7 +117,7 @@ with open("tests/resources/mountain.png", "rb") as f: engine.run("Describe the weather in the image", [image_artifact]) ``` -## AmazonBedrockImageQueryDriver +## Amazon Bedrock The [Amazon Bedrock Image Query Driver](../../reference/griptape/drivers/image_query/amazon_bedrock_image_query_driver.md) provides multi-model access to image query models hosted by Amazon Bedrock. This Driver manages API calls to the Bedrock API, while the specific Model Drivers below format the API requests and parse the responses. diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index 1006f215f..0100ccbac 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -125,38 +125,6 @@ agent = Agent( agent.run("Artificial intelligence is a technology with great promise.") ``` -### Azure OpenAI Completion - -The [AzureOpenAiCompletionPromptDriver](../../reference/griptape/drivers/prompt/azure_openai_completion_prompt_driver.md) connects to Azure OpenAI [Text Completion](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/reference) API. - -```python -import os -from griptape.structures import Agent -from griptape.drivers import AzureOpenAiCompletionPromptDriver -from griptape.config import StructureConfig - -agent = Agent( - config=StructureConfig( - prompt_driver=AzureOpenAiCompletionPromptDriver( - api_key=os.environ["AZURE_OPENAI_API_KEY_1"], - model="text-davinci-003", - azure_deployment=os.environ["AZURE_OPENAI_DAVINCI_DEPLOYMENT_ID"], - azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT_1"], - temperature=1 - ) - ) -) - -agent.run( - """ - Write a product launch email for new AI-powered headphones that are priced at $79.99 and available at Best Buy, Target and Amazon.com. The target audience is tech-savvy music lovers and the tone is friendly and exciting. - - 1. What should be the subject line of the email? - 2. What should be the body of the email? - """ -) -``` - ### Cohere The [CoherePromptDriver](../../reference/griptape/drivers/prompt/cohere_prompt_driver.md) connects to the Cohere [Generate](https://docs.cohere.ai/reference/generate) API. @@ -232,57 +200,96 @@ agent = Agent( agent.run('Briefly explain how a computer works to a young child.') ``` +### Amazon Bedrock + +!!! info + This driver requires the `drivers-prompt-amazon-bedrock` [extra](../index.md#extras). + +The [AmazonBedrockPromptDriver](../../reference/griptape/drivers/prompt/amazon_bedrock_prompt_driver.md) uses [Amazon Bedrock](https://aws.amazon.com/bedrock/)'s [Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html). + +All models supported by the Converse API are available for use with this driver. + +```python +from griptape.structures import Agent +from griptape.drivers import AmazonBedrockPromptDriver +from griptape.rules import Rule +from griptape.config import StructureConfig + +agent = Agent( + config=StructureConfig( + prompt_driver=AmazonBedrockPromptDriver( + model="anthropic.claude-3-sonnet-20240229-v1:0", + ) + ), + rules=[ + Rule( + value="You are a customer service agent that is classifying emails by type. I want you to give your answer and then explain it." + ) + ], +) +agent.run( + """How would you categorize this email? + + Can I use my Mixmaster 4000 to mix paint, or is it only meant for mixing food? + + + Categories are: + (A) Pre-sale question + (B) Broken or defective item + (C) Billing question + (D) Other (please explain)""" +) +``` + +### Ollama + +!!! info + This driver requires the `drivers-prompt-ollama` [extra](../index.md#extras). + +The [OllamaPromptDriver](../../reference/griptape/drivers/prompt/ollama_prompt_driver.md) connects to the [Ollama Chat Completion API](https://github.com/ollama/ollama/blob/main/docs/api.md#generate-a-chat-completion). + +```python +from griptape.config import StructureConfig +from griptape.drivers import OllamaPromptDriver +from griptape.structures import Agent + + +agent = Agent( + config=StructureConfig( + prompt_driver=OllamaPromptDriver( + model="llama3", + ), + ), +) +agent.run("What color is the sky at different times of the day?") +``` + ### Hugging Face Hub !!! info This driver requires the `drivers-prompt-huggingface` [extra](../index.md#extras). -The [HuggingFaceHubPromptDriver](../../reference/griptape/drivers/prompt/huggingface_hub_prompt_driver.md) connects to the [Hugging Face Hub API](https://huggingface.co/docs/hub/api). It supports models with the following tasks: +The [HuggingFaceHubPromptDriver](../../reference/griptape/drivers/prompt/huggingface_hub_prompt_driver.md) connects to the [Hugging Face Hub API](https://huggingface.co/docs/hub/api). -- text2text-generation -- text-generation !!! warning Not all models featured on the Hugging Face Hub are supported by this driver. Models that are not supported by [Hugging Face serverless inference](https://huggingface.co/docs/api-inference/en/index) will not work with this driver. Due to the limitations of Hugging Face serverless inference, only models that are than 10GB are supported. -!!! info - The `prompt_stack_to_string_converter` function is intended to convert a `PromptStack` to model specific input. You - should consult the model's documentation to determine the correct format. - -Let's recreate the [Falcon-7B-Instruct](https://huggingface.co/tiiuae/falcon-7b-instruct) example using Griptape: - ```python import os from griptape.structures import Agent from griptape.drivers import HuggingFaceHubPromptDriver from griptape.rules import Rule, Ruleset -from griptape.utils import PromptStack from griptape.config import StructureConfig -def prompt_stack_to_string_converter(prompt_stack: PromptStack) -> str: - prompt_lines = [] - - for i in prompt_stack.inputs: - if i.is_user(): - prompt_lines.append(f"User: {i.content}") - elif i.is_assistant(): - prompt_lines.append(f"Girafatron: {i.content}") - else: - prompt_lines.append(f"Instructions: {i.content}") - prompt_lines.append("Girafatron:") - - return "\n".join(prompt_lines) - - agent = Agent( config=StructureConfig( prompt_driver=HuggingFaceHubPromptDriver( - model="tiiuae/falcon-7b-instruct", + model="HuggingFaceH4/zephyr-7b-beta", api_token=os.environ["HUGGINGFACE_HUB_ACCESS_TOKEN"], - prompt_stack_to_string=prompt_stack_to_string_converter, ) ), rulesets=[ @@ -294,7 +301,7 @@ agent = Agent( "Girafatron is obsessed with giraffes, the most glorious animal on the face of this Earth. " "Giraftron believes all other animals are irrelevant when compared to the glorious majesty of the giraffe." ) - ] + ], ) ], ) @@ -330,262 +337,68 @@ agent.run("Write the code for a snake game.") !!! info This driver requires the `drivers-prompt-huggingface-pipeline` [extra](../index.md#extras). -The [HuggingFacePipelinePromptDriver](../../reference/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.md) uses [Hugging Face Pipelines](https://huggingface.co/docs/transformers/main_classes/pipelines) for inference locally. It supports models with the following tasks: - -- text2text-generation -- text-generation +The [HuggingFacePipelinePromptDriver](../../reference/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.md) uses [Hugging Face Pipelines](https://huggingface.co/docs/transformers/main_classes/pipelines) for inference locally. !!! warning Running a model locally can be a computationally expensive process. ```python -import os from griptape.structures import Agent from griptape.drivers import HuggingFacePipelinePromptDriver from griptape.rules import Rule, Ruleset -from griptape.utils import PromptStack from griptape.config import StructureConfig -# Override the default Prompt Stack to string converter -# to format the prompt in a way that is easier for this model to understand. -def prompt_stack_to_string_converter(prompt_stack: PromptStack) -> str: - prompt_lines = [] - - for i in prompt_stack.inputs: - if i.is_user(): - prompt_lines.append(f"User: {i.content}") - elif i.is_assistant(): - prompt_lines.append(f"Girafatron: {i.content}") - else: - prompt_lines.append(f"Instructions: {i.content}") - prompt_lines.append("Girafatron:") - - return "\n".join(prompt_lines) - - agent = Agent( config=StructureConfig( prompt_driver=HuggingFacePipelinePromptDriver( - model="TinyLlama/TinyLlama-1.1B-Chat-v0.6", - prompt_stack_to_string=prompt_stack_to_string_converter, + model="TinyLlama/TinyLlama-1.1B-Chat-v1.0", ) ), rulesets=[ Ruleset( - name="Girafatron", + name="Pirate", rules=[ Rule( - value="You are Girafatron, a giraffe-obsessed robot. You are talking to a human. " - "Girafatron is obsessed with giraffes, the most glorious animal on the face of this Earth. " - "Giraftron believes all other animals are irrelevant when compared to the glorious majesty of the giraffe." + value="You are a pirate chatbot who always responds in pirate speak!" ) - ] + ], ) ], ) -agent.run("Hello Girafatron, what is your favorite animal?") +agent.run("How many helicopters can a human eat in one sitting?") ``` -### Multi Model Prompt Drivers -Certain LLM providers such as Amazon SageMaker and Amazon Bedrock supports many types of models, each with their own slight differences in prompt structure and parameters. To support this variation across models, these Prompt Drivers takes a [Prompt Model Driver](../../reference/griptape/drivers/prompt_model/base_prompt_model_driver.md) -through the [prompt_model_driver](../../reference/griptape/drivers/prompt/base_multi_model_prompt_driver.md#griptape.drivers.prompt.base_multi_model_prompt_driver.BaseMultiModelPromptDriver.prompt_model_driver) parameter. -[Prompt Model Driver](../../reference/griptape/drivers/prompt_model/base_prompt_model_driver.md)s allows for model-specific customization for Prompt Drivers. - - -#### Amazon SageMaker +### Amazon SageMaker Jumpstart !!! info This driver requires the `drivers-prompt-amazon-sagemaker` [extra](../index.md#extras). -The [AmazonSageMakerPromptDriver](../../reference/griptape/drivers/prompt/amazon_sagemaker_prompt_driver.md) uses [Amazon SageMaker Endpoints](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html) for inference on AWS. - -!!! info - For single model endpoints, the `model` parameter does not need to be specified. - For multi-model endpoints, the `model` parameter should be the inference component name. - -!!! warning - Make sure that the selected prompt model driver is compatible with the selected model. Note that even the same - logical model can require different prompt model drivers depending on how it is bundled in the endpoint. For - example, the reponse format are different for `Meta-Llama-3-8B-Instruct` when deployed via - "Amazon SageMaker JumpStart" and "Hugging Face on Amazon SageMaker". +The [AmazonSageMakerJumpstartPromptDriver](../../reference/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.md) uses [Amazon SageMaker Jumpstart](https://docs.aws.amazon.com/sagemaker/latest/dg/studio-jumpstart.html) for inference on AWS. -##### Llama - -!!! info - `SageMakerLlamaPromptModelDriver` requires a tokenizer corresponding to a [Gated Model](https://huggingface.co/docs/hub/en/models-gated) on Hugging Face. +Amazon Sagemaker Jumpstart provides a wide range of models with varying capabilities. +This Driver has been primarily _chat-optimized_ models that have a [Huggingface Chat Template](https://huggingface.co/docs/transformers/en/chat_templating) available. +If your model does not fit this use-case, we suggest sub-classing [AmazonSageMakerJumpstartPromptDriver](../../reference/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.md) and overriding the `_to_model_input` and `_to_model_params` methods. - Make sure to request access to the [Meta-Llama-3-8B-Instruct](https://huggingface.co/meta-llama/Meta-Llama-3-8B-Instruct) model on Hugging Face and configure your environment for hugging face use. - -```python title="PYTEST_IGNORE" -import os -from griptape.structures import Agent -from griptape.drivers import ( - AmazonSageMakerPromptDriver, - SageMakerLlamaPromptModelDriver, -) -from griptape.rules import Rule -from griptape.config import StructureConfig - -agent = Agent( - config=StructureConfig( - prompt_driver=AmazonSageMakerPromptDriver( - endpoint=os.environ["SAGEMAKER_LLAMA_3_INSTRUCT_ENDPOINT_NAME"], - model=os.environ["SAGEMAKER_LLAMA_3_INSTRUCT_INFERENCE_COMPONENT_NAME"], - prompt_model_driver=SageMakerLlamaPromptModelDriver(), - temperature=0.75, - ) - ), - rules=[ - Rule( - value="You are a helpful, respectful and honest assistant who is also a swarthy pirate." - "You only speak like a pirate and you never break character." - ) - ], -) - -agent.run("Hello!") -``` - -##### Falcon ```python title="PYTEST_IGNORE" import os from griptape.structures import Agent from griptape.drivers import ( - AmazonSageMakerPromptDriver, + AmazonSageMakerJumpstartPromptDriver, SageMakerFalconPromptModelDriver, ) from griptape.config import StructureConfig agent = Agent( config=StructureConfig( - prompt_driver=AmazonSageMakerPromptDriver( - endpoint=os.environ["SAGEMAKER_FALCON_ENDPOINT_NAME"], - model=os.environ["SAGEMAKER_FALCON_INFERENCE_COMPONENT_NAME"], - prompt_model_driver=SageMakerFalconPromptModelDriver(), + prompt_driver=AmazonSageMakerJumpstartPromptDriver( + endpoint=os.environ["SAGEMAKER_LLAMA_3_INSTRUCT_ENDPOINT_NAME"], + model="meta-llama/Meta-Llama-3-8B-Instruct", ) ) ) agent.run("What is a good lasagna recipe?") - -``` - -#### Amazon Bedrock - -!!! info - This driver requires the `drivers-prompt-amazon-bedrock` [extra](../index.md#extras). - -The [AmazonBedrockPromptDriver](../../reference/griptape/drivers/prompt/amazon_bedrock_prompt_driver.md) uses [Amazon Bedrock](https://aws.amazon.com/bedrock/) for inference on AWS. - -##### Amazon Titan - -To use this model with Amazon Bedrock, use the [BedrockTitanPromptModelDriver](../../reference/griptape/drivers/prompt_model/bedrock_titan_prompt_model_driver.md). - -```python -from griptape.structures import Agent -from griptape.drivers import AmazonBedrockPromptDriver, BedrockTitanPromptModelDriver -from griptape.config import StructureConfig - -agent = Agent( - config=StructureConfig( - prompt_driver=AmazonBedrockPromptDriver( - model="amazon.titan-text-express-v1", - prompt_model_driver=BedrockTitanPromptModelDriver( - top_p=1, - ) - ) - ) -) -agent.run( - "Write an informational article for children about how birds fly." - "Compare how birds fly to how airplanes fly." - 'Make sure to use the word "Thrust" at least three times.' -) -``` - -##### Anthropic Claude - -To use this model with Amazon Bedrock, use the [BedrockClaudePromptModelDriver](../../reference/griptape/drivers/prompt_model/bedrock_claude_prompt_model_driver.md). - -```python -from griptape.structures import Agent -from griptape.drivers import AmazonBedrockPromptDriver, BedrockClaudePromptModelDriver -from griptape.rules import Rule -from griptape.config import StructureConfig - -agent = Agent( - config=StructureConfig( - prompt_driver=AmazonBedrockPromptDriver( - model="anthropic.claude-3-sonnet-20240229-v1:0", - prompt_model_driver=BedrockClaudePromptModelDriver( - top_p=1, - ) - ) - ), - rules=[ - Rule( - value="You are a customer service agent that is classifying emails by type. I want you to give your answer and then explain it." - ) - ], -) -agent.run( - """How would you categorize this email? - - Can I use my Mixmaster 4000 to mix paint, or is it only meant for mixing food? - - - Categories are: - (A) Pre-sale question - (B) Broken or defective item - (C) Billing question - (D) Other (please explain)""" -) -``` -##### Meta Llama 2 - -To use this model with Amazon Bedrock, use the [BedrockLlamaPromptModelDriver](../../reference/griptape/drivers/prompt_model/bedrock_llama_prompt_model_driver.md). - -```python -from griptape.structures import Agent -from griptape.drivers import AmazonBedrockPromptDriver, BedrockLlamaPromptModelDriver -from griptape.config import StructureConfig - -agent = Agent( - config=StructureConfig( - prompt_driver=AmazonBedrockPromptDriver( - model="meta.llama2-13b-chat-v1", - prompt_model_driver=BedrockLlamaPromptModelDriver(), - ) - ) -) -agent.run( - "Write an article about impact of high inflation to GDP of a country" -) -``` - -##### Ai21 Jurassic - -To use this model with Amazon Bedrock, use the [BedrockJurassicPromptModelDriver](../../reference/griptape/drivers/prompt_model/bedrock_jurassic_prompt_model_driver.md). - -```python -from griptape.structures import Agent -from griptape.drivers import AmazonBedrockPromptDriver, BedrockJurassicPromptModelDriver -from griptape.config import StructureConfig - -agent = Agent( - config=StructureConfig( - prompt_driver=AmazonBedrockPromptDriver( - model="ai21.j2-ultra-v1", - prompt_model_driver=BedrockJurassicPromptModelDriver(top_p=0.95), - temperature=0.7, - ) - ) -) -agent.run( - "Suggest an outline for a blog post based on a title. " - "Title: How I put the pro in prompt engineering." -) ``` diff --git a/docs/griptape-framework/drivers/sql-drivers.md b/docs/griptape-framework/drivers/sql-drivers.md index 35377849a..c4b7dbcca 100644 --- a/docs/griptape-framework/drivers/sql-drivers.md +++ b/docs/griptape-framework/drivers/sql-drivers.md @@ -1,14 +1,14 @@ ## Overview SQL drivers can be used to make SQL queries and load table schemas. They are used by the [SqlLoader](../../reference/griptape/loaders/sql_loader.md) to process data. All loaders implement the following methods: -* `execute_query()` executes a query and returns [RowResult](../../reference/griptape/drivers/sql/base_sql_driver.md#griptape.drivers.sql.base_sql_driver.BaseSqlDriver.RowResult.md)s. +* `execute_query()` executes a query and returns [RowResult](../../reference/griptape/drivers/sql/base_sql_driver.md#griptape.drivers.sql.base_sql_driver.BaseSqlDriver.RowResult)s. * `execute_query_row()` executes a query and returns a raw result from SQL. * `get_table_schema()` returns a table schema. !!! info More database-specific SQL drivers are coming soon. -## SqlDriver +## SQL This is a basic SQL loader based on [SQLAlchemy 1.x](https://docs.sqlalchemy.org/en/14/). Here is an example of how to use it: @@ -22,7 +22,7 @@ driver = SqlDriver( driver.execute_query("select 'foo', 'bar';") ``` -## AmazonRedshiftSqlDriver +## Amazon Redshift !!! info This driver requires the `drivers-sql-redshift` [extra](../index.md#extras). @@ -46,7 +46,7 @@ driver = AmazonRedshiftSqlDriver( driver.execute_query("select * from people;") ``` -## SnowflakeSqlDriver +## Snowflake !!! info This driver requires the `drivers-sql-snowflake` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/structure-run-drivers.md b/docs/griptape-framework/drivers/structure-run-drivers.md index c2b94190c..54413c3a2 100644 --- a/docs/griptape-framework/drivers/structure-run-drivers.md +++ b/docs/griptape-framework/drivers/structure-run-drivers.md @@ -2,7 +2,7 @@ Structure Run Drivers can be used to run Griptape Structures in a variety of runtime environments. When combined with the [Structure Run Task](../../griptape-framework/structures/tasks.md#structure-run-task) or [Structure Run Client](../../griptape-tools/official-tools/structure-run-client.md) you can create complex, multi-agent pipelines that span multiple runtime environments. -## Local Structure Run Driver +## Local The [LocalStructureRunDriver](../../reference/griptape/drivers/structure_run/local_structure_run_driver.md) is used to run Griptape Structures in the same runtime environment as the code that is running the Structure. @@ -53,7 +53,7 @@ joke_coordinator = Pipeline( joke_coordinator.run("Tell me a joke") ``` -## Griptape Cloud Structure Run Driver +## Griptape Cloud The [GriptapeCloudStructureRunDriver](../../reference/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.md) is used to run Griptape Structures in the Griptape Cloud. diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 73a416c84..481a2dd84 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -16,7 +16,7 @@ Each vector driver takes a [BaseEmbeddingDriver](../../reference/griptape/driver !!! info More vector drivers are coming soon. -## Local Vector Store Driver +## Local The [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) can be used to load and query data from memory. Here is a complete example of how the driver can be used to load a webpage into the driver and query it later: @@ -47,7 +47,7 @@ print("\n\n".join(values)) ``` -## Pinecone Vector Store Driver +## Pinecone !!! info This driver requires the `drivers-vector-pinecone` [extra](../index.md#extras). @@ -103,7 +103,7 @@ result = vector_store_driver.query( ) ``` -## Marqo Vector Store Driver +## Marqo !!! info This driver requires the `drivers-vector-marqo` [extra](../index.md#extras). @@ -157,7 +157,7 @@ result = vector_store.query(query="What is griptape?") print(result) ``` -## Mongodb Atlas Vector Store Driver +## Mongodb Atlas !!! info This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). @@ -225,14 +225,14 @@ The format for creating a vector index should look similar to the following: ``` Replace `path_to_vector` with the expected field name where the vector content will be. -## Azure MongoDB Vector Store Driver +## Azure MongoDB !!! info This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). The [AzureMongoDbVectorStoreDriver](../../reference/griptape/drivers/vector/azure_mongodb_vector_store_driver.md) provides support for storing vector data in an Azure CosmosDb database account using the MongoDb vCore API -Here is an example of how the driver can be used to load and query information in an Azure CosmosDb MongoDb vCore database. It is almost the same as the [MongodbAtlasVectorStoreDriver](#mongodb-atlas-vector-store-driver): +Here is an example of how the driver can be used to load and query information in an Azure CosmosDb MongoDb vCore database. It is very similar to the Driver for [MongoDb Atlas](#mongodb-atlas): ```python from griptape.drivers import AzureMongoDbVectorStoreDriver, OpenAiEmbeddingDriver @@ -274,7 +274,7 @@ result = vector_store.query(query="What is griptape?") print(result) ``` -## Redis Vector Store Driver +## Redis !!! info This driver requires the `drivers-vector-redis` [extra](../index.md#extras). @@ -319,7 +319,7 @@ The format for creating a vector index should be similar to the following: FT.CREATE idx:griptape ON hash PREFIX 1 "griptape:" SCHEMA namespace TAG vector VECTOR FLAT 6 TYPE FLOAT32 DIM 1536 DISTANCE_METRIC COSINE ``` -## OpenSearch Vector Store Driver +## OpenSearch !!! info This driver requires the `drivers-vector-opensearch` [extra](../index.md#extras). @@ -372,7 +372,7 @@ The body mappings for creating a vector index should look similar to the followi } ``` -## PGVector Vector Store Driver +## PGVector !!! info This driver requires the `drivers-vector-postgresql` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/web-scraper-drivers.md b/docs/griptape-framework/drivers/web-scraper-drivers.md index 888605b73..a02365b67 100644 --- a/docs/griptape-framework/drivers/web-scraper-drivers.md +++ b/docs/griptape-framework/drivers/web-scraper-drivers.md @@ -4,7 +4,7 @@ Web Scraper Drivers can be used to scrape text from the web. They are used by [W * `scrape_url()` scrapes text from a website and returns a [TextArtifact](../../reference/griptape/artifacts/text_artifact.md). The format of the scrapped text is determined by the Driver. -## Markdownify Web Scraper Driver +## Markdownify !!! info This driver requires the `drivers-web-scraper-markdownify` [extra](../index.md#extras) and the @@ -64,7 +64,7 @@ agent = Agent( agent.run("List all email addresses on griptape.ai in a flat numbered markdown list.") ``` -## Trafilatura Web Scraper Driver +## Trafilatura !!! info This driver requires the `drivers-web-scraper-trafilatura` [extra](../index.md#extras). diff --git a/docs/griptape-framework/engines/audio-engines.md b/docs/griptape-framework/engines/audio-engines.md index cbef1ef23..6494d5365 100644 --- a/docs/griptape-framework/engines/audio-engines.md +++ b/docs/griptape-framework/engines/audio-engines.md @@ -2,7 +2,7 @@ [Audio Generation Engines](../../reference/griptape/engines/audio/index.md) facilitate audio generation. Audio Generation Engines provides a `run` method that accepts the necessary inputs for its particular mode and provides the request to the configured [Driver](../drivers/text-to-speech-drivers.md). -### Text to Speech Engine +### Text to Speech This Engine facilitates synthesizing speech from text inputs. @@ -28,7 +28,7 @@ engine.run( ) ``` -### Audio Transcription Engine +### Audio Transcription The [Audio Transcription Engine](../../reference/griptape/engines/audio/audio_transcription_engine.md) facilitates transcribing speech from audio inputs. diff --git a/docs/griptape-framework/engines/extraction-engines.md b/docs/griptape-framework/engines/extraction-engines.md index f7969ff4a..101f81ba8 100644 --- a/docs/griptape-framework/engines/extraction-engines.md +++ b/docs/griptape-framework/engines/extraction-engines.md @@ -3,7 +3,7 @@ Extraction Engines in Griptape facilitate the extraction of data from text forma These engines play a crucial role in the functionality of [Extraction Tasks](../../griptape-framework/structures/tasks.md). As of now, Griptape supports two types of Extraction Engines: the CSV Extraction Engine and the JSON Extraction Engine. -## CSV Extraction Engine +## CSV The CSV Extraction Engine is designed specifically for extracting data from CSV-formatted content. @@ -39,7 +39,7 @@ Bob,35,California Charlie,40,Texas ``` -## JSON Extraction Engine +## JSON The JSON Extraction Engine is tailored for extracting data from JSON-formatted content. diff --git a/docs/griptape-framework/engines/image-generation-engines.md b/docs/griptape-framework/engines/image-generation-engines.md index 0c3997fa9..9d38fd197 100644 --- a/docs/griptape-framework/engines/image-generation-engines.md +++ b/docs/griptape-framework/engines/image-generation-engines.md @@ -39,7 +39,7 @@ engine.run( ) ``` -### Prompt Image Generation Engine +### Prompt Image This Engine facilitates generating images from text prompts. @@ -65,7 +65,7 @@ engine.run( ) ``` -### Variation Image Generation Engine +### Variation This Engine facilitates generating variations of an input image according to a text prompt. The input image is used as a reference for the model's generation. @@ -95,7 +95,7 @@ engine.run( ) ``` -### Inpainting Image Generation Engine +### Inpainting This Engine facilitates inpainting, or modifying an input image according to a text prompt within the bounds of a mask defined by mask image. After inpainting, the area specified by the mask is replaced with the model's generation, while the rest of the input image remains the same. @@ -130,7 +130,7 @@ engine.run( ) ``` -### Outpainting Image Generation Engine +### Outpainting This Engine facilitates outpainting, or modifying an input image according to a text prompt outside the bounds of a mask defined by a mask image. After outpainting, the area of the input image specified by the mask remains the same, while the rest is replaced with the model's generation. diff --git a/docs/griptape-framework/engines/image-query-engines.md b/docs/griptape-framework/engines/image-query-engines.md deleted file mode 100644 index 0457657f8..000000000 --- a/docs/griptape-framework/engines/image-query-engines.md +++ /dev/null @@ -1,25 +0,0 @@ -# ImageQueryEngine - -The [Image Query Engine](../../reference/griptape/engines/image_query/image_query_engine.md) is used to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular [Image Query Driver](../drivers/image-query-drivers.md). - -All Image Query Drivers default to a `max_tokens` of 256. You can tune this value based on your use case and the [Image Query Driver](../drivers/image-query-drivers.md) you are providing. - -```python -from griptape.drivers import OpenAiImageQueryDriver -from griptape.engines import ImageQueryEngine -from griptape.loaders import ImageLoader - -driver = OpenAiImageQueryDriver( - model="gpt-4o", - max_tokens=256 -) - -engine = ImageQueryEngine( - image_query_driver=driver -) - -with open("tests/resources/mountain.png", "rb") as f: - image_artifact = ImageLoader().load(f.read()) - -engine.run("Describe the weather in the image", [image_artifact]) -``` diff --git a/docs/griptape-framework/engines/query-engines.md b/docs/griptape-framework/engines/query-engines.md index 8acd4686d..38f5f6610 100644 --- a/docs/griptape-framework/engines/query-engines.md +++ b/docs/griptape-framework/engines/query-engines.md @@ -1,13 +1,13 @@ ## Overview -Query engines are used to search collections of text. +Query engines are used to perform text queries against various modalities. -## VectorQueryEngine +## Vector -Used to query vector storages. You can set a custom [prompt_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.prompt_driver.md) and [vector_store_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.vector_store_driver.md). Uses [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) by default. +Used to query vector storages. You can set a custom [prompt_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.prompt_driver) and [vector_store_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.vector_store_driver). Uses [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) by default. -Use the [upsert_text_artifact](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.upsert_text_artifact.md) method to insert [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s into vector storage with an optional `namespace`. +Use the [upsert_text_artifact](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.upsert_text_artifact)s into vector storage with an optional `namespace`. -Use the [VectorQueryEngine](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.query.md) method to query the vector storage. +Use the [VectorQueryEngine](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.query) method to query the vector storage. ```python from griptape.drivers import OpenAiChatPromptDriver, LocalVectorStoreDriver, OpenAiEmbeddingDriver @@ -25,3 +25,28 @@ engine.upsert_text_artifacts( engine.query("what is griptape?", namespace="griptape") ``` + +## Image +The [Image Query Engine](../../reference/griptape/engines/image_query/image_query_engine.md) allows you to perform natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular [Image Query Driver](../drivers/image-query-drivers.md). + +All Image Query Drivers default to a `max_tokens` of 256. You can tune this value based on your use case and the [Image Query Driver](../drivers/image-query-drivers.md) you are providing. + +```python +from griptape.drivers import OpenAiImageQueryDriver +from griptape.engines import ImageQueryEngine +from griptape.loaders import ImageLoader + +driver = OpenAiImageQueryDriver( + model="gpt-4o", + max_tokens=256 +) + +engine = ImageQueryEngine( + image_query_driver=driver +) + +with open("tests/resources/mountain.png", "rb") as f: + image_artifact = ImageLoader().load(f.read()) + +engine.run("Describe the weather in the image", [image_artifact]) +``` diff --git a/docs/griptape-framework/engines/summary-engines.md b/docs/griptape-framework/engines/summary-engines.md index 8ecc1ad09..936c12a7c 100644 --- a/docs/griptape-framework/engines/summary-engines.md +++ b/docs/griptape-framework/engines/summary-engines.md @@ -2,11 +2,11 @@ Summary engines are used to summarize text and collections of [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s. -## PromptSummaryEngine +## Prompt Used to summarize texts with LLMs. You can set a custom [prompt_driver](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.prompt_driver), [template_generator](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.template_generator), and [chunker](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.chunker). -Use the [summarize_artifacts](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.summarize_artifacts) method to summarize a list of artifacts or [summarize_text](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.summarize_text) to summarize an arbitrary string. +Use the [summarize_artifacts](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.summarize_artifacts) method to summarize a list of artifacts or [summarize_text](../../reference/griptape/engines/summary/base_summary_engine.md#griptape.engines.summary.base_summary_engine.BaseSummaryEngine.summarize_text) to summarize an arbitrary string. ```python import io diff --git a/docs/griptape-framework/misc/tokenizers.md b/docs/griptape-framework/misc/tokenizers.md index aaf488187..1920e912e 100644 --- a/docs/griptape-framework/misc/tokenizers.md +++ b/docs/griptape-framework/misc/tokenizers.md @@ -69,8 +69,8 @@ from griptape.tokenizers import HuggingFaceTokenizer tokenizer = HuggingFaceTokenizer( + model="sentence-transformers/all-MiniLM-L6-v2", max_output_tokens=512, - tokenizer=AutoTokenizer.from_pretrained("sentence-transformers/all-MiniLM-L6-v2") ) print(tokenizer.count_tokens("Hello world!")) @@ -78,57 +78,18 @@ print(tokenizer.count_input_tokens_left("Hello world!")) print(tokenizer.count_output_tokens_left("Hello world!")) ``` -### Bedrock - -#### Anthropic Claude +### Amazon Bedrock ```python -from griptape.tokenizers import BedrockClaudeTokenizer +from griptape.tokenizers import AmazonBedrockTokenizer -tokenizer = BedrockClaudeTokenizer(model="anthropic.claude-3-sonnet-20240229-v1:0") +tokenizer = AmazonBedrockTokenizer(model="amazon.titan-text-express-v1") print(tokenizer.count_tokens("Hello world!")) print(tokenizer.count_input_tokens_left("Hello world!")) print(tokenizer.count_output_tokens_left("Hello world!")) ``` -#### Amazon Titan -```python -from griptape.tokenizers import BedrockTitanTokenizer - - -tokenizer = BedrockTitanTokenizer(model="amazon.titan-text-express-v1") - -print(tokenizer.count_tokens("Hello world!")) -print(tokenizer.count_input_tokens_left("Hello world!")) -print(tokenizer.count_output_tokens_left("Hello world!")) -``` - -#### Meta Llama 2 -```python -from griptape.tokenizers import BedrockLlamaTokenizer - - -tokenizer = BedrockLlamaTokenizer(model="meta.llama2-13b-chat-v1") - -print(tokenizer.count_tokens("Hello world!")) -print(tokenizer.count_input_tokens_left("Hello world!")) -print(tokenizer.count_output_tokens_left("Hello world!")) -``` - -#### Ai21 Jurassic -```python -from griptape.tokenizers import BedrockJurassicTokenizer - - -tokenizer = BedrockJurassicTokenizer(model="ai21.j2-ultra-v1") - -print(tokenizer.count_tokens("Hello world!")) -print(tokenizer.count_input_tokens_left("Hello world!")) -print(tokenizer.count_output_tokens_left("Hello world!")) -``` - - ### Simple Not all LLM providers have a public tokenizer API. In this case, you can use the `SimpleTokenizer` to count tokens based on a simple heuristic. diff --git a/docs/griptape-framework/structures/config.md b/docs/griptape-framework/structures/config.md index 9637eaf35..d75354768 100644 --- a/docs/griptape-framework/structures/config.md +++ b/docs/griptape-framework/structures/config.md @@ -89,7 +89,7 @@ agent = Agent( ### Custom Configs -You can create your own [StructureConfig](../../reference/griptape/config/structure_config.md) by overriding the Drivers in [default_config](../../reference/griptape/config/structure_config.md#griptape.config.structure_config.StructureConfig.default_config). +You can create your own [StructureConfig](../../reference/griptape/config/structure_config.md) by overriding relevant Drivers. The [StructureConfig](../../reference/griptape/config/structure_config.md) class includes "Dummy" Drivers for all types, which throw a [DummyException](../../reference/griptape/exceptions/dummy_exception.md) if invoked without being overridden. This approach ensures that you are informed through clear error messages if you attempt to use Structures without proper Driver configurations. diff --git a/docs/griptape-framework/structures/conversation-memory.md b/docs/griptape-framework/structures/conversation-memory.md index 92fdf98c4..1707a2ad9 100644 --- a/docs/griptape-framework/structures/conversation-memory.md +++ b/docs/griptape-framework/structures/conversation-memory.md @@ -57,7 +57,7 @@ agent.run("Hello!") print(agent.conversation_memory) ``` -You can set the [max_runs](../../reference/griptape/memory/structure/conversation_memory.md#griptape.memory.structure.conversation_memory.ConversationMemory.max_runs) parameter to limit how many runs are kept in memory. +You can set the [max_runs](../../reference/griptape/memory/structure/base_conversation_memory.md#griptape.memory.structure.base_conversation_memory.BaseConversationMemory.max_runs) parameter to limit how many runs are kept in memory. ```python from griptape.structures import Agent diff --git a/docs/griptape-framework/structures/rulesets.md b/docs/griptape-framework/structures/rulesets.md index d97ea65cb..f245579b7 100644 --- a/docs/griptape-framework/structures/rulesets.md +++ b/docs/griptape-framework/structures/rulesets.md @@ -154,7 +154,7 @@ pipeline.run("I love skateboarding!") ### Rules -You can pass [rules](../../reference/griptape/tasks/prompt_task.md#griptape.tasks.prompt_task.PromptTask.rules) directly to the Task to have a Ruleset created for you. +You can pass [rules](../../reference/griptape/mixins/rule_mixin.md#griptape.mixins.rule_mixin.RuleMixin.rules) directly to the Task to have a Ruleset created for you. ```python from griptape.structures import Pipeline diff --git a/docs/griptape-framework/structures/task-memory.md b/docs/griptape-framework/structures/task-memory.md index f76094dad..219fd4412 100644 --- a/docs/griptape-framework/structures/task-memory.md +++ b/docs/griptape-framework/structures/task-memory.md @@ -206,7 +206,6 @@ from griptape.config import ( ) from griptape.drivers import ( AmazonBedrockPromptDriver, - BedrockTitanPromptModelDriver, AmazonBedrockTitanEmbeddingDriver, LocalVectorStoreDriver, OpenAiChatPromptDriver, @@ -227,7 +226,6 @@ agent = Agent( query_engine=VectorQueryEngine( prompt_driver=AmazonBedrockPromptDriver( model="amazon.titan-text-express-v1", - prompt_model_driver=BedrockTitanPromptModelDriver(), ), vector_store_driver=LocalVectorStoreDriver( embedding_driver=AmazonBedrockTitanEmbeddingDriver() diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index 0f05ea3e2..53b1b702e 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -627,7 +627,7 @@ pipeline.run("An image of a mountain shrouded by clouds") ## Image Query Task -The [Image Query Task](../../reference/griptape/tasks/image_query_task.md) executes a natural language query on one or more input images. This Task uses an [Image Query Engine](../engines/image-query-engines.md) configured with an [Image Query Driver](../drivers/image-query-drivers.md) to perform the query. The functionality provided by this Task depend on the capabilities of the model provided by the Driver. +The [Image Query Task](../../reference/griptape/tasks/image_query_task.md) performs a natural language query on one or more input images. This Task uses an [Image Query Engine](../engines/query-engines.md#image) configured with an [Image Query Driver](../drivers/image-query-drivers.md) to perform the query. The functionality provided by this Task depend on the capabilities of the model provided by the Driver. This Task accepts two inputs: a query (represented by either a string or a [Text Artifact](../data/artifacts.md#textartifact)) and a list of [Image Artifacts](../data/artifacts.md#imageartifact) or a Callable returning these two values. @@ -668,7 +668,7 @@ pipeline.run("Describe the weather in the image") ``` ## Structure Run Task -The [Structure Run Task](../../reference/griptape/tasks/structure_run_task.md) executes another Structure with a given input. +The [Structure Run Task](../../reference/griptape/tasks/structure_run_task.md) runs another Structure with a given input. This Task is useful for orchestrating multiple specialized Structures in a single run. Note that the input to the Task is a tuple of arguments that will be passed to the Structure. ```python diff --git a/docs/griptape-framework/structures/workflows.md b/docs/griptape-framework/structures/workflows.md index 3c2bac25a..9490ca1c4 100644 --- a/docs/griptape-framework/structures/workflows.md +++ b/docs/griptape-framework/structures/workflows.md @@ -7,7 +7,8 @@ A [Workflow](../../reference/griptape/structures/workflow.md) is a non-sequentia Workflows have access to the following [context](../../reference/griptape/structures/workflow.md#griptape.structures.workflow.Workflow.context) variables in addition to the [base context](./tasks.md#context): -* `parent_outputs`: outputs into the current task referenceable by parent task IDs. +* `parent_outputs`: dictionary containing mapping of parent IDs to their outputs. +* `parents_output_text`: string containing the concatenated outputs of all parent tasks. * `parents`: parent tasks referenceable by IDs. * `children`: child tasks referenceable by IDs. @@ -17,8 +18,16 @@ Let's build a simple workflow. Let's say, we want to write a story in a fantasy ```python from griptape.tasks import PromptTask from griptape.structures import Workflow +from griptape.utils import StructureVisualizer -workflow = Workflow() + +world_task = PromptTask( + "Create a fictional world based on the following key words {{ keywords|join(', ') }}", + context={ + "keywords": ["fantasy", "ocean", "tidal lock"] + }, + id="world" +) def character_task(task_id, character_name) -> PromptTask: return PromptTask( @@ -26,34 +35,29 @@ def character_task(task_id, character_name) -> PromptTask: context={ "name": character_name }, - id=task_id + id=task_id, + parent_ids=["world"] ) -world_task = PromptTask( - "Create a fictional world based on the following key words {{ keywords|join(', ') }}", - context={ - "keywords": ["fantasy", "ocean", "tidal lock"] - }, - id="world" -) -workflow.add_task(world_task) +scotty_task = character_task("scotty", "Scotty") +annie_task = character_task("annie", "Annie") story_task = PromptTask( "Based on the following description of the world and characters, write a short story:\n{{ parent_outputs['world'] }}\n{{ parent_outputs['scotty'] }}\n{{ parent_outputs['annie'] }}", - id="story" + id="story", + parent_ids=["world", "scotty", "annie"] ) -workflow.add_task(story_task) -character_task_1 = character_task("scotty", "Scotty") -character_task_2 = character_task("annie", "Annie") +workflow = Workflow(tasks=[world_task, story_task, scotty_task, annie_task, story_task]) -# Note the preserve_relationship flag. This ensures that world_task remains a parent of -# story_task so its output can be referenced in the story_task prompt. -workflow.insert_tasks(world_task, [character_task_1, character_task_2], story_task, preserve_relationship=True) +print(StructureVisualizer(workflow).to_url()) workflow.run() ``` +Note that we use the `StructureVisualizer` to get a visual representation of the workflow. If we visit the printed url, it should look like this: + +![Workflow](https://mermaid.ink/img/Z3JhcGggVEQ7OwoJd29ybGQtLT4gc3RvcnkgJiBzY290dHkgJiBhbm5pZTsKCXNjb3R0eS0tPiBzdG9yeTsKCWFubmllLS0+IHN0b3J5Ow==) !!! Info Output edited for brevity @@ -147,3 +151,208 @@ workflow.run() unity and harmony that can exist in diversity. ``` +### Declarative vs Imperative Syntax + +The above example showed how to create a workflow using the declarative syntax via the `parent_ids` init param, but there are a number of declarative and imperative options for you to choose between. There is no functional difference, they merely exist to allow you to structure your code as is most readable for your use case. Possibilities are illustrated below. + +Declaratively specify parents (same as above example): + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +workflow = Workflow( + tasks=[ + PromptTask("Name an animal", id="animal"), + PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective", parent_ids=["animal"]), + PromptTask("Name a {{ parent_outputs['adjective'] }} animal", id="new-animal", parent_ids=["adjective"]), + ], + rules=[Rule("output a single lowercase word")] +) + +workflow.run() +``` + +Declaratively specify children: + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +workflow = Workflow( + tasks=[ + PromptTask("Name an animal", id="animal", child_ids=["adjective"]), + PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective", child_ids=["new-animal"]), + PromptTask("Name a {{ parent_outputs['adjective'] }} animal", id="new-animal"), + ], + rules=[Rule("output a single lowercase word")], +) + +workflow.run() +``` + +Declaratively specifying a mix of parents and children: + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +workflow = Workflow( + tasks=[ + PromptTask("Name an animal", id="animal"), + PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective", parent_ids=["animal"], child_ids=["new-animal"]), + PromptTask("Name a {{ parent_outputs['adjective'] }} animal", id="new-animal"), + ], + rules=[Rule("output a single lowercase word")], +) + +workflow.run() +``` + +Imperatively specify parents: + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +animal_task = PromptTask("Name an animal", id="animal") +adjective_task = PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective") +new_animal_task = PromptTask("Name a {{ parent_outputs['adjective'] }} animal", id="new-animal") + +adjective_task.add_parent(animal_task) +new_animal_task.add_parent(adjective_task) + +workflow = Workflow( + tasks=[animal_task, adjective_task, new_animal_task], + rules=[Rule("output a single lowercase word")], +) + +workflow.run() +``` + +Imperatively specify children: + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +animal_task = PromptTask("Name an animal", id="animal") +adjective_task = PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective") +new_animal_task = PromptTask("Name a {{ parent_outputs['adjective'] }} animal", id="new-animal") + +animal_task.add_child(adjective_task) +adjective_task.add_child(new_animal_task) + +workflow = Workflow( + tasks=[animal_task, adjective_task, new_animal_task], + rules=[Rule("output a single lowercase word")], +) + +workflow.run() +``` + +Imperatively specify a mix of parents and children: + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +animal_task = PromptTask("Name an animal", id="animal") +adjective_task = PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective") +new_animal_task = PromptTask("Name a {{ parent_outputs['adjective'] }} animal", id="new-animal") + +adjective_task.add_parent(animal_task) +adjective_task.add_child(new_animal_task) + +workflow = Workflow( + tasks=[animal_task, adjective_task, new_animal_task], + rules=[Rule("output a single lowercase word")], +) + +workflow.run() +``` + +Or even mix imperative and declarative: + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +animal_task = PromptTask("Name an animal", id="animal") +adjective_task = PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective", parent_ids=["animal"]) + + +new_animal_task = PromptTask("Name a {{ parent_outputs['adjective'] }} animal", id="new-animal") +new_animal_task.add_parent(adjective_task) + +workflow = Workflow( + tasks=[animal_task, adjective_task, new_animal_task], + rules=[Rule("output a single lowercase word")], +) + +workflow.run() +``` + +### Insert Parallel Tasks + +`Workflow.insert_tasks()` provides a convenient way to insert parallel tasks between parents and children. + +!!! info + By default, all children are removed from the parent task and all parent tasks are removed from the child task. If you want to keep these parent-child relationships, then set the `preserve_relationship` parameter to `True`. + +Imperatively insert parallel tasks between a parent and child: + +```python +from griptape.tasks import PromptTask +from griptape.structures import Workflow +from griptape.rules import Rule + +workflow = Workflow( + rules=[Rule("output a single lowercase word")], +) + +animal_task = PromptTask("Name an animal", id="animal") +adjective_task = PromptTask("Describe {{ parent_outputs['animal'] }} with an adjective", id="adjective") +color_task = PromptTask("Describe {{ parent_outputs['animal'] }} with a color", id="color") +new_animal_task = PromptTask("Name an animal described as: \n{{ parents_output_text }}", id="new-animal") + +# The following workflow runs animal_task, then (adjective_task, and color_task) +# in parallel, then finally new_animal_task. +# +# In other words, the output of animal_task is passed to both adjective_task and color_task +# and the outputs of adjective_task and color_task are then passed to new_animal_task. +workflow.add_task(animal_task) +workflow.add_task(new_animal_task) +workflow.insert_tasks(animal_task, [adjective_task, color_task], new_animal_task) + +workflow.run() +``` + +output: +``` +[06/18/24 09:52:21] INFO PromptTask animal + Input: Name an animal +[06/18/24 09:52:22] INFO PromptTask animal + Output: elephant + INFO PromptTask adjective + Input: Describe elephant with an adjective + INFO PromptTask color + Input: Describe elephant with a color + INFO PromptTask color + Output: gray + INFO PromptTask adjective + Output: majestic + INFO PromptTask new-animal + Input: Name an animal described as: + majestic + gray +[06/18/24 09:52:23] INFO PromptTask new-animal + Output: elephant +``` diff --git a/docs/griptape-framework/tools/index.md b/docs/griptape-framework/tools/index.md index 0ae8054af..4d604a77c 100644 --- a/docs/griptape-framework/tools/index.md +++ b/docs/griptape-framework/tools/index.md @@ -1,4 +1,4 @@ -# Overview +## Overview One of the most powerful features of Griptape is the ability for Toolkit Tasks to generate _chains of thought_ (CoT) and use tools that can interact with the outside world. We use the [ReAct](https://arxiv.org/abs/2210.03629) technique to implement CoT reasoning and acting in the underlying LLMs without using any fine-tuning. diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index f2cc452ad..793bf24ad 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -21,6 +21,11 @@ class BaseChunker(ABC): default=Factory(lambda self: self.tokenizer.max_input_tokens, takes_self=True), kw_only=True ) + @max_tokens.validator # pyright: ignore + def validate_max_tokens(self, _, max_tokens: int) -> None: + if max_tokens < 0: + raise ValueError("max_tokens must be 0 or greater.") + def chunk(self, text: TextArtifact | str) -> list[TextArtifact]: text = text.value if isinstance(text, TextArtifact) else text diff --git a/griptape/config/__init__.py b/griptape/config/__init__.py index 7783b3886..541eb0db0 100644 --- a/griptape/config/__init__.py +++ b/griptape/config/__init__.py @@ -8,6 +8,7 @@ from .amazon_bedrock_structure_config import AmazonBedrockStructureConfig from .anthropic_structure_config import AnthropicStructureConfig from .google_structure_config import GoogleStructureConfig +from .cohere_structure_config import CohereStructureConfig __all__ = [ @@ -19,4 +20,5 @@ "AmazonBedrockStructureConfig", "AnthropicStructureConfig", "GoogleStructureConfig", + "CohereStructureConfig", ] diff --git a/griptape/config/amazon_bedrock_structure_config.py b/griptape/config/amazon_bedrock_structure_config.py index cefb97f57..e70d9c819 100644 --- a/griptape/config/amazon_bedrock_structure_config.py +++ b/griptape/config/amazon_bedrock_structure_config.py @@ -11,7 +11,6 @@ BasePromptDriver, BaseVectorStoreDriver, BedrockClaudeImageQueryModelDriver, - BedrockClaudePromptModelDriver, BedrockTitanImageGenerationModelDriver, LocalVectorStoreDriver, ) @@ -21,11 +20,7 @@ class AmazonBedrockStructureConfig(StructureConfig): prompt_driver: BasePromptDriver = field( default=Factory( - lambda: AmazonBedrockPromptDriver( - model="anthropic.claude-3-sonnet-20240229-v1:0", - stream=False, - prompt_model_driver=BedrockClaudePromptModelDriver(), - ) + lambda: AmazonBedrockPromptDriver(model="anthropic.claude-3-sonnet-20240229-v1:0", stream=False) ), metadata={"serializable": True}, ) diff --git a/griptape/config/cohere_structure_config.py b/griptape/config/cohere_structure_config.py new file mode 100644 index 000000000..82f11b8f4 --- /dev/null +++ b/griptape/config/cohere_structure_config.py @@ -0,0 +1,37 @@ +from attrs import Factory, define, field + +from griptape.config import StructureConfig +from griptape.drivers import ( + BaseEmbeddingDriver, + BasePromptDriver, + CoherePromptDriver, + CohereEmbeddingDriver, + BaseVectorStoreDriver, + LocalVectorStoreDriver, +) + + +@define +class CohereStructureConfig(StructureConfig): + api_key: str = field(metadata={"serializable": False}, kw_only=True) + + prompt_driver: BasePromptDriver = field( + default=Factory(lambda self: CoherePromptDriver(model="command-r", api_key=self.api_key), takes_self=True), + metadata={"serializable": True}, + kw_only=True, + ) + embedding_driver: BaseEmbeddingDriver = field( + default=Factory( + lambda self: CohereEmbeddingDriver( + model="embed-english-v3.0", api_key=self.api_key, input_type="search_document" + ), + takes_self=True, + ), + metadata={"serializable": True}, + kw_only=True, + ) + vector_store_driver: BaseVectorStoreDriver = field( + default=Factory(lambda self: LocalVectorStoreDriver(embedding_driver=self.embedding_driver), takes_self=True), + kw_only=True, + metadata={"serializable": True}, + ) diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index f44602f8b..8e8128d7a 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -1,17 +1,15 @@ from .prompt.base_prompt_driver import BasePromptDriver from .prompt.openai_chat_prompt_driver import OpenAiChatPromptDriver -from .prompt.openai_completion_prompt_driver import OpenAiCompletionPromptDriver from .prompt.azure_openai_chat_prompt_driver import AzureOpenAiChatPromptDriver -from .prompt.azure_openai_completion_prompt_driver import AzureOpenAiCompletionPromptDriver from .prompt.cohere_prompt_driver import CoherePromptDriver from .prompt.huggingface_pipeline_prompt_driver import HuggingFacePipelinePromptDriver from .prompt.huggingface_hub_prompt_driver import HuggingFaceHubPromptDriver from .prompt.anthropic_prompt_driver import AnthropicPromptDriver -from .prompt.amazon_sagemaker_prompt_driver import AmazonSageMakerPromptDriver +from .prompt.amazon_sagemaker_jumpstart_prompt_driver import AmazonSageMakerJumpstartPromptDriver from .prompt.amazon_bedrock_prompt_driver import AmazonBedrockPromptDriver from .prompt.google_prompt_driver import GooglePromptDriver -from .prompt.base_multi_model_prompt_driver import BaseMultiModelPromptDriver from .prompt.dummy_prompt_driver import DummyPromptDriver +from .prompt.ollama_prompt_driver import OllamaPromptDriver from .memory.conversation.base_conversation_memory_driver import BaseConversationMemoryDriver from .memory.conversation.local_conversation_memory_driver import LocalConversationMemoryDriver @@ -21,18 +19,14 @@ from .embedding.base_embedding_driver import BaseEmbeddingDriver from .embedding.openai_embedding_driver import OpenAiEmbeddingDriver from .embedding.azure_openai_embedding_driver import AzureOpenAiEmbeddingDriver -from .embedding.base_multi_model_embedding_driver import BaseMultiModelEmbeddingDriver -from .embedding.amazon_sagemaker_embedding_driver import AmazonSageMakerEmbeddingDriver +from .embedding.amazon_sagemaker_jumpstart_embedding_driver import AmazonSageMakerJumpstartEmbeddingDriver from .embedding.amazon_bedrock_titan_embedding_driver import AmazonBedrockTitanEmbeddingDriver from .embedding.amazon_bedrock_cohere_embedding_driver import AmazonBedrockCohereEmbeddingDriver from .embedding.voyageai_embedding_driver import VoyageAiEmbeddingDriver from .embedding.huggingface_hub_embedding_driver import HuggingFaceHubEmbeddingDriver from .embedding.google_embedding_driver import GoogleEmbeddingDriver from .embedding.dummy_embedding_driver import DummyEmbeddingDriver - -from .embedding_model.base_embedding_model_driver import BaseEmbeddingModelDriver -from .embedding_model.sagemaker_huggingface_embedding_model_driver import SageMakerHuggingFaceEmbeddingModelDriver -from .embedding_model.sagemaker_tensorflow_hub_embedding_model_driver import SageMakerTensorFlowHubEmbeddingModelDriver +from .embedding.cohere_embedding_driver import CohereEmbeddingDriver from .vector.base_vector_store_driver import BaseVectorStoreDriver from .vector.local_vector_store_driver import LocalVectorStoreDriver @@ -51,14 +45,6 @@ from .sql.snowflake_sql_driver import SnowflakeSqlDriver from .sql.sql_driver import SqlDriver -from .prompt_model.base_prompt_model_driver import BasePromptModelDriver -from .prompt_model.sagemaker_llama_prompt_model_driver import SageMakerLlamaPromptModelDriver -from .prompt_model.sagemaker_falcon_prompt_model_driver import SageMakerFalconPromptModelDriver -from .prompt_model.bedrock_titan_prompt_model_driver import BedrockTitanPromptModelDriver -from .prompt_model.bedrock_claude_prompt_model_driver import BedrockClaudePromptModelDriver -from .prompt_model.bedrock_jurassic_prompt_model_driver import BedrockJurassicPromptModelDriver -from .prompt_model.bedrock_llama_prompt_model_driver import BedrockLlamaPromptModelDriver - from .image_generation_model.base_image_generation_model_driver import BaseImageGenerationModelDriver from .image_generation_model.bedrock_stable_diffusion_image_generation_model_driver import ( BedrockStableDiffusionImageGenerationModelDriver, @@ -115,18 +101,16 @@ __all__ = [ "BasePromptDriver", "OpenAiChatPromptDriver", - "OpenAiCompletionPromptDriver", "AzureOpenAiChatPromptDriver", - "AzureOpenAiCompletionPromptDriver", "CoherePromptDriver", "HuggingFacePipelinePromptDriver", "HuggingFaceHubPromptDriver", "AnthropicPromptDriver", - "AmazonSageMakerPromptDriver", + "AmazonSageMakerJumpstartPromptDriver", "AmazonBedrockPromptDriver", "GooglePromptDriver", - "BaseMultiModelPromptDriver", "DummyPromptDriver", + "OllamaPromptDriver", "BaseConversationMemoryDriver", "LocalConversationMemoryDriver", "AmazonDynamoDbConversationMemoryDriver", @@ -134,17 +118,14 @@ "BaseEmbeddingDriver", "OpenAiEmbeddingDriver", "AzureOpenAiEmbeddingDriver", - "BaseMultiModelEmbeddingDriver", - "AmazonSageMakerEmbeddingDriver", + "AmazonSageMakerJumpstartEmbeddingDriver", "AmazonBedrockTitanEmbeddingDriver", "AmazonBedrockCohereEmbeddingDriver", "VoyageAiEmbeddingDriver", "HuggingFaceHubEmbeddingDriver", "GoogleEmbeddingDriver", "DummyEmbeddingDriver", - "BaseEmbeddingModelDriver", - "SageMakerHuggingFaceEmbeddingModelDriver", - "SageMakerTensorFlowHubEmbeddingModelDriver", + "CohereEmbeddingDriver", "BaseVectorStoreDriver", "LocalVectorStoreDriver", "PineconeVectorStoreDriver", @@ -160,13 +141,6 @@ "AmazonRedshiftSqlDriver", "SnowflakeSqlDriver", "SqlDriver", - "BasePromptModelDriver", - "SageMakerLlamaPromptModelDriver", - "SageMakerFalconPromptModelDriver", - "BedrockTitanPromptModelDriver", - "BedrockClaudePromptModelDriver", - "BedrockJurassicPromptModelDriver", - "BedrockLlamaPromptModelDriver", "BaseImageGenerationModelDriver", "BedrockStableDiffusionImageGenerationModelDriver", "BedrockTitanImageGenerationModelDriver", diff --git a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py index 15ce67c4c..903022f86 100644 --- a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py @@ -3,7 +3,8 @@ from typing import Any, TYPE_CHECKING from attrs import define, field, Factory from griptape.drivers import BaseEmbeddingDriver -from griptape.tokenizers import BedrockCohereTokenizer +from griptape.tokenizers.amazon_bedrock_tokenizer import AmazonBedrockTokenizer +from griptape.tokenizers.base_tokenizer import BaseTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: @@ -28,8 +29,8 @@ class AmazonBedrockCohereEmbeddingDriver(BaseEmbeddingDriver): model: str = field(default=DEFAULT_MODEL, kw_only=True) input_type: str = field(default="search_query", kw_only=True) session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) - tokenizer: BedrockCohereTokenizer = field( - default=Factory(lambda self: BedrockCohereTokenizer(model=self.model), takes_self=True), kw_only=True + tokenizer: BaseTokenizer = field( + default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True ) bedrock_client: Any = field( default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), kw_only=True diff --git a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py index a510c618c..b754b0608 100644 --- a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py @@ -3,7 +3,8 @@ from typing import Any, TYPE_CHECKING from attrs import define, field, Factory from griptape.drivers import BaseEmbeddingDriver -from griptape.tokenizers import BedrockTitanTokenizer +from griptape.tokenizers.amazon_bedrock_tokenizer import AmazonBedrockTokenizer +from griptape.tokenizers.base_tokenizer import BaseTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: @@ -24,8 +25,8 @@ class AmazonBedrockTitanEmbeddingDriver(BaseEmbeddingDriver): model: str = field(default=DEFAULT_MODEL, kw_only=True, metadata={"serializable": True}) session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) - tokenizer: BedrockTitanTokenizer = field( - default=Factory(lambda self: BedrockTitanTokenizer(model=self.model), takes_self=True), kw_only=True + tokenizer: BaseTokenizer = field( + default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True ) bedrock_client: Any = field( default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), kw_only=True diff --git a/griptape/drivers/embedding/amazon_sagemaker_embedding_driver.py b/griptape/drivers/embedding/amazon_sagemaker_embedding_driver.py deleted file mode 100644 index 4ab6d2bf7..000000000 --- a/griptape/drivers/embedding/amazon_sagemaker_embedding_driver.py +++ /dev/null @@ -1,31 +0,0 @@ -from __future__ import annotations -from typing import TYPE_CHECKING -import json -from typing import Any - -from attrs import Factory, define, field - -from griptape.drivers import BaseMultiModelEmbeddingDriver -from griptape.utils import import_optional_dependency - -if TYPE_CHECKING: - from griptape.drivers import BaseEmbeddingModelDriver - import boto3 - - -@define -class AmazonSageMakerEmbeddingDriver(BaseMultiModelEmbeddingDriver): - session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) - sagemaker_client: Any = field( - default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), kw_only=True - ) - embedding_model_driver: BaseEmbeddingModelDriver = field(kw_only=True) - - def try_embed_chunk(self, chunk: str) -> list[float]: - payload = self.embedding_model_driver.chunk_to_model_params(chunk) - endpoint_response = self.sagemaker_client.invoke_endpoint( - EndpointName=self.model, ContentType="application/x-text", Body=json.dumps(payload).encode("utf-8") - ) - - response = json.loads(endpoint_response.get("Body").read().decode("utf-8")) - return self.embedding_model_driver.process_output(response) diff --git a/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py b/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py new file mode 100644 index 000000000..2b764c2f4 --- /dev/null +++ b/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py @@ -0,0 +1,53 @@ +from __future__ import annotations +from typing import TYPE_CHECKING +import json +from typing import Any, Optional + +from attrs import Factory, define, field + +from griptape.drivers import BaseEmbeddingDriver +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + import boto3 + + +@define +class AmazonSageMakerJumpstartEmbeddingDriver(BaseEmbeddingDriver): + session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) + sagemaker_client: Any = field( + default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), kw_only=True + ) + endpoint: str = field(kw_only=True, metadata={"serializable": True}) + custom_attributes: str = field(default="accept_eula=true", kw_only=True, metadata={"serializable": True}) + inference_component_name: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + + def try_embed_chunk(self, chunk: str) -> list[float]: + payload = {"text_inputs": chunk, "mode": "embedding"} + + endpoint_response = self.sagemaker_client.invoke_endpoint( + EndpointName=self.endpoint, + ContentType="application/json", + Body=json.dumps(payload).encode("utf-8"), + CustomAttributes=self.custom_attributes, + **( + {"InferenceComponentName": self.inference_component_name} + if self.inference_component_name is not None + else {} + ), + ) + + response = json.loads(endpoint_response.get("Body").read().decode("utf-8")) + + if "embedding" in response: + embedding = response["embedding"] + + if embedding: + if isinstance(embedding[0], list): + return embedding[0] + else: + return embedding + else: + raise ValueError("model response is empty") + else: + raise ValueError("invalid response from model") diff --git a/griptape/drivers/embedding/base_multi_model_embedding_driver.py b/griptape/drivers/embedding/base_multi_model_embedding_driver.py deleted file mode 100644 index 90f827ad2..000000000 --- a/griptape/drivers/embedding/base_multi_model_embedding_driver.py +++ /dev/null @@ -1,15 +0,0 @@ -from __future__ import annotations -from abc import ABC -from typing import TYPE_CHECKING - -from attrs import define, field - -from griptape.drivers import BaseEmbeddingDriver - -if TYPE_CHECKING: - from griptape.drivers import BaseEmbeddingModelDriver - - -@define -class BaseMultiModelEmbeddingDriver(BaseEmbeddingDriver, ABC): - embedding_model_driver: BaseEmbeddingModelDriver = field(kw_only=True) diff --git a/griptape/drivers/embedding/cohere_embedding_driver.py b/griptape/drivers/embedding/cohere_embedding_driver.py new file mode 100644 index 000000000..5e8bdf4dd --- /dev/null +++ b/griptape/drivers/embedding/cohere_embedding_driver.py @@ -0,0 +1,43 @@ +from __future__ import annotations +from typing import TYPE_CHECKING +from attrs import define, field, Factory +from griptape.drivers import BaseEmbeddingDriver +from griptape.tokenizers import CohereTokenizer +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from cohere import Client + + +@define +class CohereEmbeddingDriver(BaseEmbeddingDriver): + """ + Attributes: + api_key: Cohere API key. + model: Cohere model name. + client: Custom `cohere.Client`. + tokenizer: Custom `CohereTokenizer`. + input_type: Cohere embedding input type. + """ + + DEFAULT_MODEL = "models/embedding-001" + + api_key: str = field(kw_only=True, metadata={"serializable": False}) + client: Client = field( + default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True), + kw_only=True, + ) + tokenizer: CohereTokenizer = field( + default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True), + kw_only=True, + ) + + input_type: str = field(kw_only=True, metadata={"serializable": True}) + + def try_embed_chunk(self, chunk: str) -> list[float]: + result = self.client.embed(texts=[chunk], model=self.model, input_type=self.input_type) + + if isinstance(result.embeddings, list): + return result.embeddings[0] + else: + raise ValueError("Non-float embeddings are not supported.") diff --git a/griptape/drivers/embedding_model/base_embedding_model_driver.py b/griptape/drivers/embedding_model/base_embedding_model_driver.py deleted file mode 100644 index ad7bf3bda..000000000 --- a/griptape/drivers/embedding_model/base_embedding_model_driver.py +++ /dev/null @@ -1,11 +0,0 @@ -from attrs import define -from abc import ABC, abstractmethod - - -@define -class BaseEmbeddingModelDriver(ABC): - @abstractmethod - def chunk_to_model_params(self, chunk: str) -> dict: ... - - @abstractmethod - def process_output(self, output: dict) -> list[float]: ... diff --git a/griptape/drivers/embedding_model/sagemaker_huggingface_embedding_model_driver.py b/griptape/drivers/embedding_model/sagemaker_huggingface_embedding_model_driver.py deleted file mode 100644 index dceffcd8a..000000000 --- a/griptape/drivers/embedding_model/sagemaker_huggingface_embedding_model_driver.py +++ /dev/null @@ -1,11 +0,0 @@ -from attrs import define -from griptape.drivers import BaseEmbeddingModelDriver - - -@define -class SageMakerHuggingFaceEmbeddingModelDriver(BaseEmbeddingModelDriver): - def chunk_to_model_params(self, chunk: str) -> dict: - return {"text_inputs": chunk} - - def process_output(self, output: dict) -> list[float]: - return output["embedding"][0] diff --git a/griptape/drivers/embedding_model/sagemaker_tensorflow_hub_embedding_model_driver.py b/griptape/drivers/embedding_model/sagemaker_tensorflow_hub_embedding_model_driver.py deleted file mode 100644 index 9d9632fb0..000000000 --- a/griptape/drivers/embedding_model/sagemaker_tensorflow_hub_embedding_model_driver.py +++ /dev/null @@ -1,11 +0,0 @@ -from attrs import define -from griptape.drivers import BaseEmbeddingModelDriver - - -@define -class SageMakerTensorFlowHubEmbeddingModelDriver(BaseEmbeddingModelDriver): - def chunk_to_model_params(self, chunk: str) -> dict: - return {"text_inputs": chunk} - - def process_output(self, output: dict) -> list[float]: - return output["embedding"] diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 0675e7f92..849ed0901 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -1,55 +1,75 @@ from __future__ import annotations -import json -from typing import TYPE_CHECKING, Any + from collections.abc import Iterator -from attrs import define, field, Factory +from typing import TYPE_CHECKING, Any + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact +from griptape.drivers import BasePromptDriver +from griptape.tokenizers import AmazonBedrockTokenizer, BaseTokenizer from griptape.utils import import_optional_dependency -from .base_multi_model_prompt_driver import BaseMultiModelPromptDriver if TYPE_CHECKING: - from griptape.utils import PromptStack import boto3 + from griptape.utils import PromptStack + @define -class AmazonBedrockPromptDriver(BaseMultiModelPromptDriver): +class AmazonBedrockPromptDriver(BasePromptDriver): session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) bedrock_client: Any = field( default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), kw_only=True ) + additional_model_request_fields: dict = field(default=Factory(dict), kw_only=True) + tokenizer: BaseTokenizer = field( + default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True + ) def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - model_input = self.prompt_model_driver.prompt_stack_to_model_input(prompt_stack) - payload = {**self.prompt_model_driver.prompt_stack_to_model_params(prompt_stack)} - if isinstance(model_input, dict): - payload.update(model_input) + response = self.bedrock_client.converse(**self._base_params(prompt_stack)) + + output_message = response["output"]["message"] + output_content = output_message["content"][0]["text"] - response = self.bedrock_client.invoke_model( - modelId=self.model, contentType="application/json", accept="application/json", body=json.dumps(payload) - ) + return TextArtifact(output_content) - response_body = response["body"].read() + def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + response = self.bedrock_client.converse_stream(**self._base_params(prompt_stack)) - if response_body: - return self.prompt_model_driver.process_output(response_body) + stream = response.get("stream") + if stream is not None: + for event in stream: + if "contentBlockDelta" in event: + yield TextArtifact(event["contentBlockDelta"]["delta"]["text"]) else: raise Exception("model response is empty") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - model_input = self.prompt_model_driver.prompt_stack_to_model_input(prompt_stack) - payload = {**self.prompt_model_driver.prompt_stack_to_model_params(prompt_stack)} - if isinstance(model_input, dict): - payload.update(model_input) - - response = self.bedrock_client.invoke_model_with_response_stream( - modelId=self.model, contentType="application/json", accept="application/json", body=json.dumps(payload) - ) - - response_body = response["body"] - if response_body: - for chunk in response["body"]: - chunk_bytes = chunk["chunk"]["bytes"] - yield self.prompt_model_driver.process_output(chunk_bytes) + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + content = [{"text": prompt_input.content}] + + if prompt_input.is_system(): + return {"text": prompt_input.content} + elif prompt_input.is_assistant(): + return {"role": "assistant", "content": content} else: - raise Exception("model response is empty") + return {"role": "user", "content": content} + + def _base_params(self, prompt_stack: PromptStack) -> dict: + system_messages = [ + self._prompt_stack_input_to_message(input) + for input in prompt_stack.inputs + if input.is_system() and input.content + ] + messages = [ + self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs if not input.is_system() + ] + + return { + "modelId": self.model, + "messages": messages, + "system": system_messages, + "inferenceConfig": {"temperature": self.temperature}, + "additionalModelRequestFields": self.additional_model_request_fields, + } diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py new file mode 100644 index 000000000..18f8e4b77 --- /dev/null +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -0,0 +1,94 @@ +from __future__ import annotations + +import json +from collections.abc import Iterator +from typing import TYPE_CHECKING, Any, Optional + +from attrs import Factory, define, field + +from griptape.artifacts import TextArtifact +from griptape.drivers.prompt.base_prompt_driver import BasePromptDriver +from griptape.tokenizers import HuggingFaceTokenizer +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + import boto3 + + from griptape.utils import PromptStack + + +@define +class AmazonSageMakerJumpstartPromptDriver(BasePromptDriver): + session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) + sagemaker_client: Any = field( + default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), kw_only=True + ) + endpoint: str = field(kw_only=True, metadata={"serializable": True}) + custom_attributes: str = field(default="accept_eula=true", kw_only=True, metadata={"serializable": True}) + inference_component_name: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + stream: bool = field(default=False, kw_only=True, metadata={"serializable": True}) + max_tokens: int = field(default=250, kw_only=True, metadata={"serializable": True}) + tokenizer: HuggingFaceTokenizer = field( + default=Factory( + lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), takes_self=True + ), + kw_only=True, + ) + + @stream.validator # pyright: ignore + def validate_stream(self, _, stream): + if stream: + raise ValueError("streaming is not supported") + + def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + payload = {"inputs": self._to_model_input(prompt_stack), "parameters": self._to_model_params(prompt_stack)} + + response = self.sagemaker_client.invoke_endpoint( + EndpointName=self.endpoint, + ContentType="application/json", + Body=json.dumps(payload), + CustomAttributes=self.custom_attributes, + **( + {"InferenceComponentName": self.inference_component_name} + if self.inference_component_name is not None + else {} + ), + ) + + decoded_body = json.loads(response["Body"].read().decode("utf8")) + + if isinstance(decoded_body, list): + if decoded_body: + return TextArtifact(decoded_body[0]["generated_text"]) + else: + raise ValueError("model response is empty") + else: + return TextArtifact(decoded_body["generated_text"]) + + def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + raise NotImplementedError("streaming is not supported") + + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + return {"role": prompt_input.role, "content": prompt_input.content} + + def _to_model_input(self, prompt_stack: PromptStack) -> str: + prompt = self.tokenizer.tokenizer.apply_chat_template( + [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], + tokenize=False, + add_generation_prompt=True, + ) + + if isinstance(prompt, str): + return prompt + else: + raise ValueError("Invalid output type.") + + def _to_model_params(self, prompt_stack: PromptStack) -> dict: + return { + "temperature": self.temperature, + "max_new_tokens": self.max_tokens, + "do_sample": True, + "eos_token_id": self.tokenizer.tokenizer.eos_token_id, + "stop_strings": self.tokenizer.stop_sequences, + "return_full_text": False, + } diff --git a/griptape/drivers/prompt/amazon_sagemaker_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_prompt_driver.py deleted file mode 100644 index 2934ea642..000000000 --- a/griptape/drivers/prompt/amazon_sagemaker_prompt_driver.py +++ /dev/null @@ -1,52 +0,0 @@ -from __future__ import annotations -import json -from typing import TYPE_CHECKING, Any -from collections.abc import Iterator -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact -from griptape.utils import import_optional_dependency -from .base_multi_model_prompt_driver import BaseMultiModelPromptDriver - -if TYPE_CHECKING: - from griptape.utils import PromptStack - import boto3 - - -@define -class AmazonSageMakerPromptDriver(BaseMultiModelPromptDriver): - session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) - sagemaker_client: Any = field( - default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), kw_only=True - ) - endpoint: str = field(kw_only=True, metadata={"serializable": True}) - model: str = field(default=None, kw_only=True, metadata={"serializable": True}) - custom_attributes: str = field(default="accept_eula=true", kw_only=True, metadata={"serializable": True}) - stream: bool = field(default=False, kw_only=True, metadata={"serializable": True}) - - @stream.validator # pyright: ignore - def validate_stream(self, _, stream): - if stream: - raise ValueError("streaming is not supported") - - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - payload = { - "inputs": self.prompt_model_driver.prompt_stack_to_model_input(prompt_stack), - "parameters": self.prompt_model_driver.prompt_stack_to_model_params(prompt_stack), - } - response = self.sagemaker_client.invoke_endpoint( - EndpointName=self.endpoint, - ContentType="application/json", - Body=json.dumps(payload), - CustomAttributes=self.custom_attributes, - **({"InferenceComponentName": self.model} if self.model is not None else {}), - ) - - decoded_body = json.loads(response["Body"].read().decode("utf8")) - - if decoded_body: - return self.prompt_model_driver.process_output(decoded_body) - else: - raise Exception("model response is empty") - - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - raise NotImplementedError("streaming is not supported") diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 486233643..b74a9d5f6 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -5,7 +5,7 @@ from griptape.artifacts import TextArtifact from griptape.utils import PromptStack, import_optional_dependency from griptape.drivers import BasePromptDriver -from griptape.tokenizers import AnthropicTokenizer +from griptape.tokenizers import AnthropicTokenizer, BaseTokenizer @define @@ -15,7 +15,6 @@ class AnthropicPromptDriver(BasePromptDriver): api_key: Anthropic API key. model: Anthropic model name. client: Custom `Anthropic` client. - tokenizer: Custom `AnthropicTokenizer`. """ api_key: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) @@ -26,11 +25,12 @@ class AnthropicPromptDriver(BasePromptDriver): ), kw_only=True, ) - tokenizer: AnthropicTokenizer = field( + tokenizer: BaseTokenizer = field( default=Factory(lambda self: AnthropicTokenizer(model=self.model), takes_self=True), kw_only=True ) top_p: float = field(default=0.999, kw_only=True, metadata={"serializable": True}) top_k: int = field(default=250, kw_only=True, metadata={"serializable": True}) + max_tokens: int = field(default=1000, kw_only=True, metadata={"serializable": True}) def try_run(self, prompt_stack: PromptStack) -> TextArtifact: response = self.client.messages.create(**self._base_params(prompt_stack)) @@ -44,34 +44,36 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: if chunk.type == "content_block_delta": yield TextArtifact(value=chunk.delta.text) + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + content = prompt_input.content + + if prompt_input.is_system(): + return {"role": "system", "content": content} + elif prompt_input.is_assistant(): + return {"role": "assistant", "content": content} + else: + return {"role": "user", "content": content} + def _prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> dict: messages = [ - {"role": self.__to_anthropic_role(prompt_input), "content": prompt_input.content} + self._prompt_stack_input_to_message(prompt_input) for prompt_input in prompt_stack.inputs if not prompt_input.is_system() ] - system = next((i for i in prompt_stack.inputs if i.is_system()), None) + system = next((self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs if i.is_system()), None) if system is None: return {"messages": messages} else: - return {"messages": messages, "system": system.content} + return {"messages": messages, "system": system["content"]} def _base_params(self, prompt_stack: PromptStack) -> dict: return { "model": self.model, "temperature": self.temperature, "stop_sequences": self.tokenizer.stop_sequences, - "max_tokens": self.max_output_tokens(self.prompt_stack_to_string(prompt_stack)), "top_p": self.top_p, "top_k": self.top_k, + "max_tokens": self.max_tokens, **self._prompt_stack_to_model_input(prompt_stack), } - - def __to_anthropic_role(self, prompt_input: PromptStack.Input) -> str: - if prompt_input.is_system(): - return "system" - elif prompt_input.is_assistant(): - return "assistant" - else: - return "user" diff --git a/griptape/drivers/prompt/azure_openai_completion_prompt_driver.py b/griptape/drivers/prompt/azure_openai_completion_prompt_driver.py deleted file mode 100644 index 4ff2a4902..000000000 --- a/griptape/drivers/prompt/azure_openai_completion_prompt_driver.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import Callable, Optional -from attrs import define, field, Factory -from griptape.drivers import OpenAiCompletionPromptDriver -import openai - - -@define -class AzureOpenAiCompletionPromptDriver(OpenAiCompletionPromptDriver): - """ - Attributes: - azure_deployment: An optional Azure OpenAi deployment id. Defaults to the model name. - azure_endpoint: An Azure OpenAi endpoint. - azure_ad_token: An optional Azure Active Directory token. - azure_ad_token_provider: An optional Azure Active Directory token provider. - api_version: An Azure OpenAi API version. - client: An `openai.AzureOpenAI` client. - """ - - azure_deployment: str = field( - kw_only=True, default=Factory(lambda self: self.model, takes_self=True), metadata={"serializable": True} - ) - azure_endpoint: str = field(kw_only=True, metadata={"serializable": True}) - azure_ad_token: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) - azure_ad_token_provider: Optional[Callable[[], str]] = field( - kw_only=True, default=None, metadata={"serializable": False} - ) - api_version: str = field(default="2023-05-15", kw_only=True, metadata={"serializable": True}) - client: openai.AzureOpenAI = field( - default=Factory( - lambda self: openai.AzureOpenAI( - organization=self.organization, - api_key=self.api_key, - api_version=self.api_version, - azure_endpoint=self.azure_endpoint, - azure_deployment=self.azure_deployment, - azure_ad_token=self.azure_ad_token, - azure_ad_token_provider=self.azure_ad_token_provider, - ), - takes_self=True, - ) - ) diff --git a/griptape/drivers/prompt/base_multi_model_prompt_driver.py b/griptape/drivers/prompt/base_multi_model_prompt_driver.py deleted file mode 100644 index 5411ea730..000000000 --- a/griptape/drivers/prompt/base_multi_model_prompt_driver.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import annotations -from attrs import define, field -from abc import ABC -from .base_prompt_driver import BasePromptDriver -from typing import TYPE_CHECKING, Optional - -if TYPE_CHECKING: - from griptape.tokenizers import BaseTokenizer - from griptape.drivers import BasePromptModelDriver - - -@define -class BaseMultiModelPromptDriver(BasePromptDriver, ABC): - """Prompt Driver for platforms like Amazon SageMaker, and Amazon Bedrock that host many LLM models. - - Instances of this Prompt Driver require a Prompt Model Driver which is used to convert the prompt stack - into a model input and parameters, and to process the model output. - - Attributes: - model: Name of the model to use. - tokenizer: Tokenizer to use. Defaults to the Tokenizer of the Prompt Model Driver. - prompt_model_driver: Prompt Model Driver to use. - """ - - tokenizer: Optional[BaseTokenizer] = field(default=None, kw_only=True) - prompt_model_driver: BasePromptModelDriver = field(kw_only=True, metadata={"serializable": True}) - stream: bool = field(default=False, kw_only=True, metadata={"serializable": True}) - - @stream.validator # pyright: ignore - def validate_stream(self, _, stream): - if stream and not self.prompt_model_driver.supports_streaming: - raise ValueError(f"{self.prompt_model_driver.__class__.__name__} does not support streaming") - - def __attrs_post_init__(self) -> None: - self.prompt_model_driver.prompt_driver = self - - if not self.tokenizer: - self.tokenizer = self.prompt_model_driver.tokenizer diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 096035f8b..9ef076dbc 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -1,6 +1,6 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Optional, Callable +from typing import TYPE_CHECKING, Optional from collections.abc import Iterator from attrs import define, field, Factory from griptape.events import StartPromptEvent, FinishPromptEvent, CompletionChunkEvent @@ -32,9 +32,6 @@ class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): temperature: float = field(default=0.1, kw_only=True, metadata={"serializable": True}) max_tokens: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) structure: Optional[Structure] = field(default=None, kw_only=True) - prompt_stack_to_string: Callable[[PromptStack], str] = field( - default=Factory(lambda self: self.default_prompt_stack_to_string_converter, takes_self=True), kw_only=True - ) ignored_exception_types: tuple[type[Exception], ...] = field( default=Factory(lambda: (ImportError, ValueError)), kw_only=True ) @@ -42,23 +39,12 @@ class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): tokenizer: BaseTokenizer stream: bool = field(default=False, kw_only=True, metadata={"serializable": True}) - def max_output_tokens(self, text: str | list) -> int: - tokens_left = self.tokenizer.count_output_tokens_left(text) - - if self.max_tokens: - return min(self.max_tokens, tokens_left) - else: - return tokens_left - - def token_count(self, prompt_stack: PromptStack) -> int: - return self.tokenizer.count_tokens(self.prompt_stack_to_string(prompt_stack)) - def before_run(self, prompt_stack: PromptStack) -> None: if self.structure: self.structure.publish_event( StartPromptEvent( model=self.model, - token_count=self.token_count(prompt_stack), + token_count=self.tokenizer.count_tokens(self.prompt_stack_to_string(prompt_stack)), prompt_stack=prompt_stack, prompt=self.prompt_stack_to_string(prompt_stack), ) @@ -67,7 +53,9 @@ def before_run(self, prompt_stack: PromptStack) -> None: def after_run(self, result: TextArtifact) -> None: if self.structure: self.structure.publish_event( - FinishPromptEvent(model=self.model, token_count=result.token_count(self.tokenizer), result=result.value) + FinishPromptEvent( + model=self.model, result=result.value, token_count=self.tokenizer.count_tokens(result.value) + ) ) def run(self, prompt_stack: PromptStack) -> TextArtifact: @@ -92,7 +80,16 @@ def run(self, prompt_stack: PromptStack) -> TextArtifact: else: raise Exception("prompt driver failed after all retry attempts") - def default_prompt_stack_to_string_converter(self, prompt_stack: PromptStack) -> str: + def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: + """Converts a Prompt Stack to a string for token counting or model input. + This base implementation is only a rough approximation, and should be overridden by subclasses with model-specific tokens. + + Args: + prompt_stack: The Prompt Stack to convert to a string. + + Returns: + A single string representation of the Prompt Stack. + """ prompt_lines = [] for i in prompt_stack.inputs: diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index 2f85c49bf..3ff2c9e89 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -4,8 +4,8 @@ from attrs import define, field, Factory from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver -from griptape.tokenizers import CohereTokenizer from griptape.utils import PromptStack, import_optional_dependency +from griptape.tokenizers import BaseTokenizer, CohereTokenizer if TYPE_CHECKING: from cohere import Client @@ -18,48 +18,48 @@ class CoherePromptDriver(BasePromptDriver): api_key: Cohere API key. model: Cohere model name. client: Custom `cohere.Client`. - tokenizer: Custom `CohereTokenizer`. """ - api_key: str = field(kw_only=True, metadata={"serializable": True}) + api_key: str = field(kw_only=True, metadata={"serializable": False}) model: str = field(kw_only=True, metadata={"serializable": True}) client: Client = field( default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True), kw_only=True, ) - tokenizer: CohereTokenizer = field( + tokenizer: BaseTokenizer = field( default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True), kw_only=True, ) def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - result = self.client.generate(**self._base_params(prompt_stack)) + result = self.client.chat(**self._base_params(prompt_stack)) - if result.generations: - if len(result.generations) == 1: - generation = result.generations[0] - - return TextArtifact(value=generation.text.strip()) - else: - raise Exception("completion with more than one choice is not supported yet") - else: - raise Exception("model response is empty") + return TextArtifact(value=result.text) def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - result = self.client.generate( - **self._base_params(prompt_stack), - stream=True, # pyright: ignore[reportCallIssue] - ) + result = self.client.chat_stream(**self._base_params(prompt_stack)) + + for event in result: + if event.event_type == "text-generation": + yield TextArtifact(value=event.text) - for chunk in result: - yield TextArtifact(value=chunk.text) + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + if prompt_input.is_system(): + return {"role": "SYSTEM", "text": prompt_input.content} + elif prompt_input.is_user(): + return {"role": "USER", "text": prompt_input.content} + else: + return {"role": "ASSISTANT", "text": prompt_input.content} def _base_params(self, prompt_stack: PromptStack) -> dict: - prompt = self.prompt_stack_to_string(prompt_stack) + user_message = prompt_stack.inputs[-1].content + + history_messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs[:-1]] + return { - "prompt": self.prompt_stack_to_string(prompt_stack), - "model": self.model, + "message": user_message, + "chat_history": history_messages, "temperature": self.temperature, - "end_sequences": self.tokenizer.stop_sequences, - "max_tokens": self.max_output_tokens(prompt), + "stop_sequences": self.tokenizer.stop_sequences, + "max_tokens": self.max_tokens, } diff --git a/griptape/drivers/prompt/dummy_prompt_driver.py b/griptape/drivers/prompt/dummy_prompt_driver.py index f92f9cbc1..a55ecd4fe 100644 --- a/griptape/drivers/prompt/dummy_prompt_driver.py +++ b/griptape/drivers/prompt/dummy_prompt_driver.py @@ -17,3 +17,6 @@ def try_run(self, prompt_stack: PromptStack) -> TextArtifact: def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: raise DummyException(__class__.__name__, "try_stream") + + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + raise DummyException(__class__.__name__, "_prompt_stack_input_to_message") diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 9f833c035..67bc19e24 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -19,7 +19,6 @@ class GooglePromptDriver(BasePromptDriver): api_key: Google API key. model: Google model name. model_client: Custom `GenerativeModel` client. - tokenizer: Custom `GoogleTokenizer`. top_p: Optional value for top_p. top_k: Optional value for top_k. """ @@ -42,7 +41,7 @@ def try_run(self, prompt_stack: PromptStack) -> TextArtifact: inputs, generation_config=GenerationConfig( stop_sequences=self.tokenizer.stop_sequences, - max_output_tokens=self.max_output_tokens(inputs), + max_output_tokens=self.max_tokens, temperature=self.temperature, top_p=self.top_p, top_k=self.top_k, @@ -60,7 +59,7 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: stream=True, generation_config=GenerationConfig( stop_sequences=self.tokenizer.stop_sequences, - max_output_tokens=self.max_output_tokens(inputs), + max_output_tokens=self.max_tokens, temperature=self.temperature, top_p=self.top_p, top_k=self.top_k, @@ -70,6 +69,14 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: for chunk in response: yield TextArtifact(value=chunk.text) + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + parts = [prompt_input.content] + + if prompt_input.is_assistant(): + return {"role": "model", "parts": parts} + else: + return {"role": "user", "parts": parts} + def _default_model_client(self) -> GenerativeModel: genai = import_optional_dependency("google.generativeai") genai.configure(api_key=self.api_key) @@ -90,13 +97,6 @@ def _prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> list[Conten def __to_content_dict(self, prompt_input: PromptStack.Input) -> ContentDict: ContentDict = import_optional_dependency("google.generativeai.types").ContentDict + message = self._prompt_stack_input_to_message(prompt_input) - return ContentDict({"role": self.__to_google_role(prompt_input), "parts": [prompt_input.content]}) - - def __to_google_role(self, prompt_input: PromptStack.Input) -> str: - if prompt_input.is_system(): - return "user" - elif prompt_input.is_assistant(): - return "model" - else: - return "user" + return ContentDict(message) diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index 062672aa8..3edd252cb 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -42,11 +42,7 @@ class HuggingFaceHubPromptDriver(BasePromptDriver): ) tokenizer: HuggingFaceTokenizer = field( default=Factory( - lambda self: HuggingFaceTokenizer( - tokenizer=import_optional_dependency("transformers").AutoTokenizer.from_pretrained(self.model), - max_output_tokens=self.max_tokens, - ), - takes_self=True, + lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), takes_self=True ), kw_only=True, ) @@ -55,7 +51,7 @@ def try_run(self, prompt_stack: PromptStack) -> TextArtifact: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( - prompt, return_full_text=False, max_new_tokens=self.max_output_tokens(prompt), **self.params + prompt, return_full_text=False, max_new_tokens=self.max_tokens, **self.params ) return TextArtifact(value=response) @@ -64,8 +60,26 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( - prompt, return_full_text=False, max_new_tokens=self.max_output_tokens(prompt), stream=True, **self.params + prompt, return_full_text=False, max_new_tokens=self.max_tokens, stream=True, **self.params ) for token in response: yield TextArtifact(value=token) + + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + return {"role": prompt_input.role, "content": prompt_input.content} + + def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: + return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) + + def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: + tokens = self.tokenizer.tokenizer.apply_chat_template( + [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], + add_generation_prompt=True, + tokenize=True, + ) + + if isinstance(tokens, list): + return tokens + else: + raise ValueError("Invalid output type.") diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index bde6d5e4e..4fa291877 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -1,5 +1,7 @@ +from __future__ import annotations from collections.abc import Iterator +from typing import TYPE_CHECKING from attrs import Factory, define, field from griptape.artifacts import TextArtifact @@ -7,6 +9,9 @@ from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import PromptStack, import_optional_dependency +if TYPE_CHECKING: + from transformers import TextGenerationPipeline + @define class HuggingFacePipelinePromptDriver(BasePromptDriver): @@ -14,48 +19,66 @@ class HuggingFacePipelinePromptDriver(BasePromptDriver): Attributes: params: Custom model run parameters. model: Hugging Face Hub model name. - tokenizer: Custom `HuggingFaceTokenizer`. """ - SUPPORTED_TASKS = ["text2text-generation", "text-generation"] - DEFAULT_PARAMS = {"return_full_text": False, "num_return_sequences": 1} - max_tokens: int = field(default=250, kw_only=True, metadata={"serializable": True}) model: str = field(kw_only=True, metadata={"serializable": True}) params: dict = field(factory=dict, kw_only=True, metadata={"serializable": True}) tokenizer: HuggingFaceTokenizer = field( default=Factory( - lambda self: HuggingFaceTokenizer( - tokenizer=import_optional_dependency("transformers").AutoTokenizer.from_pretrained(self.model), - max_output_tokens=self.max_tokens, - ), - takes_self=True, + lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), takes_self=True ), kw_only=True, ) + pipe: TextGenerationPipeline = field( + default=Factory( + lambda self: import_optional_dependency("transformers").pipeline( + "text-generation", model=self.model, max_new_tokens=self.max_tokens, tokenizer=self.tokenizer.tokenizer + ), + takes_self=True, + ) + ) def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - prompt = self.prompt_stack_to_string(prompt_stack) - pipeline = import_optional_dependency("transformers").pipeline + messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs] - generator = pipeline( + result = self.pipe( + messages, + max_new_tokens=self.max_tokens, tokenizer=self.tokenizer.tokenizer, - model=self.model, - max_new_tokens=self.tokenizer.count_output_tokens_left(prompt), + stop_strings=self.tokenizer.stop_sequences, + temperature=self.temperature, + do_sample=True, ) - if generator.task in self.SUPPORTED_TASKS: - extra_params = {"pad_token_id": self.tokenizer.tokenizer.eos_token_id} - - response = generator(prompt, **(self.DEFAULT_PARAMS | extra_params | self.params)) + if isinstance(result, list): + if len(result) == 1: + generated_text = result[0]["generated_text"][-1]["content"] - if len(response) == 1: - return TextArtifact(value=response[0]["generated_text"].strip()) + return TextArtifact(value=generated_text) else: raise Exception("completion with more than one choice is not supported yet") else: - raise Exception(f"only models with the following tasks are supported: {self.SUPPORTED_TASKS}") + raise Exception("invalid output format") def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: raise NotImplementedError("streaming is not supported") + + def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: + return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) + + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + return {"role": prompt_input.role, "content": prompt_input.content} + + def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: + tokens = self.tokenizer.tokenizer.apply_chat_template( + [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], + add_generation_prompt=True, + tokenize=True, + ) + + if isinstance(tokens, list): + return tokens + else: + raise ValueError("Invalid output type.") diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py new file mode 100644 index 000000000..b21176e82 --- /dev/null +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -0,0 +1,69 @@ +from __future__ import annotations +from collections.abc import Iterator +from typing import TYPE_CHECKING, Optional +from attrs import define, field, Factory +from griptape.artifacts import TextArtifact +from griptape.drivers import BasePromptDriver +from griptape.tokenizers.base_tokenizer import BaseTokenizer +from griptape.utils import PromptStack, import_optional_dependency +from griptape.tokenizers import SimpleTokenizer + +if TYPE_CHECKING: + from ollama import Client + + +@define +class OllamaPromptDriver(BasePromptDriver): + """ + Attributes: + model: Model name. + """ + + model: str = field(kw_only=True, metadata={"serializable": True}) + host: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + client: Client = field( + default=Factory(lambda self: import_optional_dependency("ollama").Client(host=self.host), takes_self=True), + kw_only=True, + ) + tokenizer: BaseTokenizer = field( + default=Factory( + lambda self: SimpleTokenizer( + characters_per_token=4, max_input_tokens=2000, max_output_tokens=self.max_tokens + ), + takes_self=True, + ), + kw_only=True, + ) + options: dict = field( + default=Factory( + lambda self: { + "temperature": self.temperature, + "stop": self.tokenizer.stop_sequences, + "num_predict": self.max_tokens, + }, + takes_self=True, + ), + kw_only=True, + ) + + def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + response = self.client.chat(**self._base_params(prompt_stack)) + + if isinstance(response, dict): + return TextArtifact(value=response["message"]["content"]) + else: + raise Exception("invalid model response") + + def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + stream = self.client.chat(**self._base_params(prompt_stack), stream=True) + + if isinstance(stream, Iterator): + for chunk in stream: + yield TextArtifact(value=chunk["message"]["content"]) + else: + raise Exception("invalid model response") + + def _base_params(self, prompt_stack: PromptStack) -> dict: + messages = [{"role": input.role, "content": input.content} for input in prompt_stack.inputs] + + return {"messages": messages, "model": self.model, "options": self.options} diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index 3d19063d3..9545bd45a 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import Optional, Any, Literal +from typing import Optional, Literal from collections.abc import Iterator import openai from attrs import define, field, Factory @@ -7,8 +7,6 @@ from griptape.utils import PromptStack from griptape.drivers import BasePromptDriver from griptape.tokenizers import OpenAiTokenizer, BaseTokenizer -import dateparser -from datetime import datetime, timedelta @define @@ -25,12 +23,6 @@ class OpenAiChatPromptDriver(BasePromptDriver): response_format: An optional OpenAi Chat Completion response format. Currently only supports `json_object` which will enable OpenAi's JSON mode. seed: An optional OpenAi Chat Completion seed. ignored_exception_types: An optional tuple of exception types to ignore. Defaults to OpenAI's known exception types. - _ratelimit_request_limit: The maximum number of requests allowed in the current rate limit window. - _ratelimit_requests_remaining: The number of requests remaining in the current rate limit window. - _ratelimit_requests_reset_at: The time at which the current rate limit window resets. - _ratelimit_token_limit: The maximum number of tokens allowed in the current rate limit window. - _ratelimit_tokens_remaining: The number of tokens remaining in the current rate limit window. - _ratelimit_tokens_reset_at: The time at which the current rate limit window resets. """ base_url: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) @@ -64,22 +56,12 @@ class OpenAiChatPromptDriver(BasePromptDriver): ), kw_only=True, ) - _ratelimit_request_limit: Optional[int] = field(init=False, default=None) - _ratelimit_requests_remaining: Optional[int] = field(init=False, default=None) - _ratelimit_requests_reset_at: Optional[datetime] = field(init=False, default=None) - _ratelimit_token_limit: Optional[int] = field(init=False, default=None) - _ratelimit_tokens_remaining: Optional[int] = field(init=False, default=None) - _ratelimit_tokens_reset_at: Optional[datetime] = field(init=False, default=None) def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - result = self.client.chat.completions.with_raw_response.create(**self._base_params(prompt_stack)) + result = self.client.chat.completions.create(**self._base_params(prompt_stack)) - self._extract_ratelimit_metadata(result) - - parsed_result = result.parse() - - if len(parsed_result.choices) == 1: - return TextArtifact(value=parsed_result.choices[0].message.content.strip()) + if len(result.choices) == 1: + return TextArtifact(value=result.choices[0].message.content.strip()) else: raise Exception("Completion with more than one choice is not supported yet.") @@ -97,14 +79,15 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: yield TextArtifact(value=delta_content) - def token_count(self, prompt_stack: PromptStack) -> int: - if isinstance(self.tokenizer, OpenAiTokenizer): - return self.tokenizer.count_tokens(self._prompt_stack_to_messages(prompt_stack)) - else: - return self.tokenizer.count_tokens(self.prompt_stack_to_string(prompt_stack)) + def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: + content = prompt_input.content - def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict[str, Any]]: - return [{"role": self.__to_openai_role(i), "content": i.content} for i in prompt_stack.inputs] + if prompt_input.is_system(): + return {"role": "system", "content": content} + elif prompt_input.is_assistant(): + return {"role": "assistant", "content": content} + else: + return {"role": "user", "content": content} def _base_params(self, prompt_stack: PromptStack) -> dict: params = { @@ -120,7 +103,7 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: # JSON mode still requires a system input instructing the LLM to output JSON. prompt_stack.add_system_input("Provide your response as a valid JSON object.") - messages = self._prompt_stack_to_messages(prompt_stack) + messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs] if self.max_tokens is not None: params["max_tokens"] = self.max_tokens @@ -128,41 +111,3 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: params["messages"] = messages return params - - def __to_openai_role(self, prompt_input: PromptStack.Input) -> str: - if prompt_input.is_system(): - return "system" - elif prompt_input.is_assistant(): - return "assistant" - else: - return "user" - - def _extract_ratelimit_metadata(self, response): - # The OpenAI SDK's requestssession variable is global, so this hook will fire for all API requests. - # The following headers are not reliably returned in every API call, so we check for the presence of the - # headers before reading and parsing their values to prevent other SDK users from encountering KeyErrors. - reset_requests_at = response.headers.get("x-ratelimit-reset-requests") - if reset_requests_at is not None: - self._ratelimit_requests_reset_at = dateparser.parse( - reset_requests_at, settings={"PREFER_DATES_FROM": "future"} - ) - - # The dateparser utility doesn't handle sub-second durations as are sometimes returned by OpenAI's API. - # If the API returns, for example, "13ms", dateparser.parse() returns None. In this case, we will set - # the time value to the current time plus a one second buffer. - if self._ratelimit_requests_reset_at is None: - self._ratelimit_requests_reset_at = datetime.now() + timedelta(seconds=1) - - reset_tokens_at = response.headers.get("x-ratelimit-reset-tokens") - if reset_tokens_at is not None: - self._ratelimit_tokens_reset_at = dateparser.parse( - reset_tokens_at, settings={"PREFER_DATES_FROM": "future"} - ) - - if self._ratelimit_tokens_reset_at is None: - self._ratelimit_tokens_reset_at = datetime.now() + timedelta(seconds=1) - - self._ratelimit_request_limit = response.headers.get("x-ratelimit-limit-requests") - self._ratelimit_requests_remaining = response.headers.get("x-ratelimit-remaining-requests") - self._ratelimit_token_limit = response.headers.get("x-ratelimit-limit-tokens") - self._ratelimit_tokens_remaining = response.headers.get("x-ratelimit-remaining-tokens") diff --git a/griptape/drivers/prompt/openai_completion_prompt_driver.py b/griptape/drivers/prompt/openai_completion_prompt_driver.py deleted file mode 100644 index 1a738a487..000000000 --- a/griptape/drivers/prompt/openai_completion_prompt_driver.py +++ /dev/null @@ -1,83 +0,0 @@ -from typing import Optional -from collections.abc import Iterator -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack -from griptape.drivers import BasePromptDriver -from griptape.tokenizers import OpenAiTokenizer -import openai - - -@define -class OpenAiCompletionPromptDriver(BasePromptDriver): - """ - Attributes: - base_url: An optional OpenAi API URL. - api_key: An optional OpenAi API key. If not provided, the `OPENAI_API_KEY` environment variable will be used. - organization: An optional OpenAI organization. If not provided, the `OPENAI_ORG_ID` environment variable will be used. - client: An `openai.OpenAI` client. - model: An OpenAI model name. - tokenizer: An `OpenAiTokenizer`. - user: A user id. Can be used to track requests by user. - ignored_exception_types: An optional tuple of exception types to ignore. Defaults to OpenAI's known exception types. - """ - - base_url: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) - api_key: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) - organization: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) - client: openai.OpenAI = field( - default=Factory( - lambda self: openai.OpenAI(api_key=self.api_key, base_url=self.base_url, organization=self.organization), - takes_self=True, - ) - ) - model: str = field(kw_only=True, metadata={"serializable": True}) - tokenizer: OpenAiTokenizer = field( - default=Factory(lambda self: OpenAiTokenizer(model=self.model), takes_self=True), kw_only=True - ) - user: str = field(default="", kw_only=True, metadata={"serializable": True}) - ignored_exception_types: tuple[type[Exception], ...] = field( - default=Factory( - lambda: ( - openai.BadRequestError, - openai.AuthenticationError, - openai.PermissionDeniedError, - openai.NotFoundError, - openai.ConflictError, - openai.UnprocessableEntityError, - ) - ), - kw_only=True, - ) - - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - result = self.client.completions.create(**self._base_params(prompt_stack)) - - if len(result.choices) == 1: - return TextArtifact(value=result.choices[0].text.strip()) - else: - raise Exception("completion with more than one choice is not supported yet") - - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - result = self.client.completions.create(**self._base_params(prompt_stack), stream=True) - - for chunk in result: - if len(chunk.choices) == 1: - choice = chunk.choices[0] - delta_content = choice.text - yield TextArtifact(value=delta_content) - - else: - raise Exception("completion with more than one choice is not supported yet") - - def _base_params(self, prompt_stack: PromptStack) -> dict: - prompt = self.prompt_stack_to_string(prompt_stack) - - return { - "model": self.model, - "max_tokens": self.max_output_tokens(prompt), - "temperature": self.temperature, - "stop": self.tokenizer.stop_sequences, - "user": self.user, - "prompt": prompt, - } diff --git a/griptape/drivers/prompt_model/__init__.py b/griptape/drivers/prompt_model/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/griptape/drivers/prompt_model/base_prompt_model_driver.py b/griptape/drivers/prompt_model/base_prompt_model_driver.py deleted file mode 100644 index 096802370..000000000 --- a/griptape/drivers/prompt_model/base_prompt_model_driver.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import annotations -from abc import ABC, abstractmethod -from typing import Optional -from attrs import define, field -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack -from griptape.drivers import BasePromptDriver -from griptape.tokenizers import BaseTokenizer -from griptape.mixins import SerializableMixin - - -@define -class BasePromptModelDriver(SerializableMixin, ABC): - max_tokens: Optional[int] = field(default=None, kw_only=True) - prompt_driver: Optional[BasePromptDriver] = field(default=None, kw_only=True) - supports_streaming: bool = field(default=True, kw_only=True) - - @property - @abstractmethod - def tokenizer(self) -> BaseTokenizer: ... - - @abstractmethod - def prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> str | list | dict: ... - - @abstractmethod - def prompt_stack_to_model_params(self, prompt_stack: PromptStack) -> dict: ... - - @abstractmethod - def process_output(self, output: dict | list[dict] | str | bytes) -> TextArtifact: ... diff --git a/griptape/drivers/prompt_model/bedrock_claude_prompt_model_driver.py b/griptape/drivers/prompt_model/bedrock_claude_prompt_model_driver.py deleted file mode 100644 index 2b4c547a9..000000000 --- a/griptape/drivers/prompt_model/bedrock_claude_prompt_model_driver.py +++ /dev/null @@ -1,87 +0,0 @@ -from __future__ import annotations -from typing import Optional -import json -from attrs import define, field -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack -from griptape.drivers import BasePromptModelDriver, AmazonBedrockPromptDriver -from griptape.tokenizers import BedrockClaudeTokenizer - - -@define -class BedrockClaudePromptModelDriver(BasePromptModelDriver): - ANTHROPIC_VERSION = "bedrock-2023-05-31" # static string for AWS: https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-anthropic-claude-messages.html#api-inference-examples-claude-multimodal-code-example - - top_p: float = field(default=0.999, kw_only=True, metadata={"serializable": True}) - top_k: int = field(default=250, kw_only=True, metadata={"serializable": True}) - _tokenizer: BedrockClaudeTokenizer = field(default=None, kw_only=True) - prompt_driver: Optional[AmazonBedrockPromptDriver] = field(default=None, kw_only=True) - - @property - def tokenizer(self) -> BedrockClaudeTokenizer: - """Returns the tokenizer for this driver. - - We need to pass the `session` field from the Prompt Driver to the - Tokenizer. However, the Prompt Driver is not initialized until after - the Prompt Model Driver is initialized. To resolve this, we make the `tokenizer` - field a @property that is only initialized when it is first accessed. - This ensures that by the time we need to initialize the Tokenizer, the - Prompt Driver has already been initialized. - - See this thread more more information: https://github.com/griptape-ai/griptape/issues/244 - - Returns: - BedrockClaudeTokenizer: The tokenizer for this driver. - """ - if self._tokenizer: - return self._tokenizer - else: - self._tokenizer = BedrockClaudeTokenizer(model=self.prompt_driver.model) - return self._tokenizer - - def prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> dict: - messages = [ - {"role": self.__to_anthropic_role(prompt_input), "content": prompt_input.content} - for prompt_input in prompt_stack.inputs - if not prompt_input.is_system() - ] - system = next((i for i in prompt_stack.inputs if i.is_system()), None) - - if system is None: - return {"messages": messages} - else: - return {"messages": messages, "system": system.content} - - def prompt_stack_to_model_params(self, prompt_stack: PromptStack) -> dict: - input = self.prompt_stack_to_model_input(prompt_stack) - - return { - "stop_sequences": self.tokenizer.stop_sequences, - "temperature": self.prompt_driver.temperature, - "top_p": self.top_p, - "top_k": self.top_k, - "max_tokens": self.prompt_driver.max_output_tokens(self.prompt_driver.prompt_stack_to_string(prompt_stack)), - "anthropic_version": self.ANTHROPIC_VERSION, - **input, - } - - def process_output(self, output: dict | list[dict] | str | bytes) -> TextArtifact: - if isinstance(output, bytes): - body = json.loads(output.decode()) - else: - raise Exception("Output must be bytes.") - - if body["type"] == "content_block_delta": - return TextArtifact(value=body["delta"]["text"]) - elif body["type"] == "message": - return TextArtifact(value=body["content"][0]["text"]) - else: - return TextArtifact(value="") - - def __to_anthropic_role(self, prompt_input: PromptStack.Input) -> str: - if prompt_input.is_system(): - return "system" - elif prompt_input.is_assistant(): - return "assistant" - else: - return "user" diff --git a/griptape/drivers/prompt_model/bedrock_jurassic_prompt_model_driver.py b/griptape/drivers/prompt_model/bedrock_jurassic_prompt_model_driver.py deleted file mode 100644 index 4da99e88f..000000000 --- a/griptape/drivers/prompt_model/bedrock_jurassic_prompt_model_driver.py +++ /dev/null @@ -1,76 +0,0 @@ -from __future__ import annotations -from typing import Optional -import json -from attrs import define, field -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack -from griptape.drivers import BasePromptModelDriver -from griptape.tokenizers import BedrockJurassicTokenizer -from griptape.drivers import AmazonBedrockPromptDriver - - -@define -class BedrockJurassicPromptModelDriver(BasePromptModelDriver): - top_p: float = field(default=0.9, kw_only=True, metadata={"serializable": True}) - _tokenizer: BedrockJurassicTokenizer = field(default=None, kw_only=True) - prompt_driver: Optional[AmazonBedrockPromptDriver] = field(default=None, kw_only=True) - supports_streaming: bool = field(default=False, kw_only=True) - - @property - def tokenizer(self) -> BedrockJurassicTokenizer: - """Returns the tokenizer for this driver. - - We need to pass the `session` field from the Prompt Driver to the - Tokenizer. However, the Prompt Driver is not initialized until after - the Prompt Model Driver is initialized. To resolve this, we make the `tokenizer` - field a @property that is only initialized when it is first accessed. - This ensures that by the time we need to initialize the Tokenizer, the - Prompt Driver has already been initialized. - - See this thread more more information: https://github.com/griptape-ai/griptape/issues/244 - - Returns: - BedrockJurassicTokenizer: The tokenizer for this driver. - """ - if self._tokenizer: - return self._tokenizer - else: - self._tokenizer = BedrockJurassicTokenizer(model=self.prompt_driver.model) - return self._tokenizer - - def prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> dict: - prompt_lines = [] - - for i in prompt_stack.inputs: - if i.is_user(): - prompt_lines.append(f"User: {i.content}") - elif i.is_assistant(): - prompt_lines.append(f"Assistant: {i.content}") - elif i.is_system(): - prompt_lines.append(f"System: {i.content}") - else: - prompt_lines.append(i.content) - prompt_lines.append("Assistant:") - - prompt = "\n".join(prompt_lines) - - return {"prompt": prompt} - - def prompt_stack_to_model_params(self, prompt_stack: PromptStack) -> dict: - prompt = self.prompt_stack_to_model_input(prompt_stack)["prompt"] - - return { - "maxTokens": self.prompt_driver.max_output_tokens(prompt), - "temperature": self.prompt_driver.temperature, - "stopSequences": self.tokenizer.stop_sequences, - "countPenalty": {"scale": 0}, - "presencePenalty": {"scale": 0}, - "frequencyPenalty": {"scale": 0}, - } - - def process_output(self, output: dict | list[dict] | str | bytes) -> TextArtifact: - if isinstance(output, bytes): - body = json.loads(output.decode()) - else: - raise Exception("Output must be bytes.") - return TextArtifact(body["completions"][0]["data"]["text"]) diff --git a/griptape/drivers/prompt_model/bedrock_llama_prompt_model_driver.py b/griptape/drivers/prompt_model/bedrock_llama_prompt_model_driver.py deleted file mode 100644 index 951583c51..000000000 --- a/griptape/drivers/prompt_model/bedrock_llama_prompt_model_driver.py +++ /dev/null @@ -1,101 +0,0 @@ -from __future__ import annotations -import json -import itertools as it -from typing import Optional -from attrs import define, field -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack -from griptape.drivers import BasePromptModelDriver -from griptape.tokenizers import BedrockLlamaTokenizer -from griptape.drivers import AmazonBedrockPromptDriver - - -@define -class BedrockLlamaPromptModelDriver(BasePromptModelDriver): - top_p: float = field(default=0.9, kw_only=True) - _tokenizer: BedrockLlamaTokenizer = field(default=None, kw_only=True) - prompt_driver: Optional[AmazonBedrockPromptDriver] = field(default=None, kw_only=True) - - @property - def tokenizer(self) -> BedrockLlamaTokenizer: - """Returns the tokenizer for this driver. - - We need to pass the `session` field from the Prompt Driver to the - Tokenizer. However, the Prompt Driver is not initialized until after - the Prompt Model Driver is initialized. To resolve this, we make the `tokenizer` - field a @property that is only initialized when it is first accessed. - This ensures that by the time we need to initialize the Tokenizer, the - Prompt Driver has already been initialized. - - See this thread more more information: https://github.com/griptape-ai/griptape/issues/244 - - Returns: - BedrockLlamaTokenizer: The tokenizer for this driver. - """ - if self._tokenizer: - return self._tokenizer - else: - self._tokenizer = BedrockLlamaTokenizer(model=self.prompt_driver.model) - return self._tokenizer - - def prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> str: - """ - Converts a `PromptStack` to a string that can be used as the input to the model. - - Prompt structure adapted from https://huggingface.co/blog/llama2#how-to-prompt-llama-2 - - Args: - prompt_stack: The `PromptStack` to convert. - """ - prompt_lines = [] - - inputs = iter(prompt_stack.inputs) - input_pairs: list[tuple] = list(it.zip_longest(inputs, inputs)) - for input_pair in input_pairs: - first_input: PromptStack.Input = input_pair[0] - second_input: Optional[PromptStack.Input] = input_pair[1] - - if first_input.is_system(): - prompt_lines.append(f"[INST] <>\n{first_input.content}\n<>\n\n") - if second_input: - if second_input.is_user(): - prompt_lines.append(f"{second_input.content} [/INST]") - else: - raise Exception("System input must be followed by user input.") - elif first_input.is_assistant(): - prompt_lines.append(f" {first_input.content} ") - if second_input: - if second_input.is_user(): - prompt_lines.append(f"[INST] {second_input.content} [/INST]") - else: - raise Exception("Assistant input must be followed by user input.") - elif first_input.is_user(): - prompt_lines.append(f"[INST] {first_input.content} [/INST]") - if second_input: - if second_input.is_assistant(): - prompt_lines.append(f" {second_input.content} ") - else: - raise Exception("User input must be followed by assistant input.") - - return "".join(prompt_lines) - - def prompt_stack_to_model_params(self, prompt_stack: PromptStack) -> dict: - prompt = self.prompt_stack_to_model_input(prompt_stack) - - return { - "prompt": prompt, - "max_gen_len": self.prompt_driver.max_output_tokens(prompt), - "temperature": self.prompt_driver.temperature, - "top_p": self.top_p, - } - - def process_output(self, output: dict | list[dict] | str | bytes) -> TextArtifact: - # When streaming, the response body comes back as bytes. - if isinstance(output, bytes): - output = output.decode() - elif isinstance(output, list) or isinstance(output, dict): - raise Exception("Invalid output format.") - - body = json.loads(output) - - return TextArtifact(body["generation"]) diff --git a/griptape/drivers/prompt_model/bedrock_titan_prompt_model_driver.py b/griptape/drivers/prompt_model/bedrock_titan_prompt_model_driver.py deleted file mode 100644 index 5f5bbc1d2..000000000 --- a/griptape/drivers/prompt_model/bedrock_titan_prompt_model_driver.py +++ /dev/null @@ -1,83 +0,0 @@ -from __future__ import annotations -from typing import Optional -import json -from attrs import define, field -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack -from griptape.drivers import BasePromptModelDriver -from griptape.tokenizers import BedrockTitanTokenizer -from griptape.drivers import AmazonBedrockPromptDriver - - -@define -class BedrockTitanPromptModelDriver(BasePromptModelDriver): - top_p: float = field(default=0.9, kw_only=True, metadata={"serializable": True}) - _tokenizer: BedrockTitanTokenizer = field(default=None, kw_only=True) - prompt_driver: Optional[AmazonBedrockPromptDriver] = field(default=None, kw_only=True) - - @property - def tokenizer(self) -> BedrockTitanTokenizer: - """Returns the tokenizer for this driver. - - We need to pass the `session` field from the Prompt Driver to the - Tokenizer. However, the Prompt Driver is not initialized until after - the Prompt Model Driver is initialized. To resolve this, we make the `tokenizer` - field a @property that is only initialized when it is first accessed. - This ensures that by the time we need to initialize the Tokenizer, the - Prompt Driver has already been initialized. - - See this thread for more information: https://github.com/griptape-ai/griptape/issues/244 - - Returns: - BedrockTitanTokenizer: The tokenizer for this driver. - """ - if self._tokenizer: - return self._tokenizer - else: - self._tokenizer = BedrockTitanTokenizer(model=self.prompt_driver.model) - return self._tokenizer - - def prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> dict: - prompt_lines = [] - - for i in prompt_stack.inputs: - if i.is_user(): - prompt_lines.append(f"User: {i.content}") - elif i.is_assistant(): - prompt_lines.append(f"Bot: {i.content}") - elif i.is_system(): - prompt_lines.append(f"Instructions: {i.content}") - else: - prompt_lines.append(i.content) - prompt_lines.append("Bot:") - - prompt = "\n\n".join(prompt_lines) - - return {"inputText": prompt} - - def prompt_stack_to_model_params(self, prompt_stack: PromptStack) -> dict: - prompt = self.prompt_stack_to_model_input(prompt_stack)["inputText"] - - return { - "textGenerationConfig": { - "maxTokenCount": self.prompt_driver.max_output_tokens(prompt), - "stopSequences": self.tokenizer.stop_sequences, - "temperature": self.prompt_driver.temperature, - "topP": self.top_p, - } - } - - def process_output(self, output: dict | list[dict] | str | bytes) -> TextArtifact: - # When streaming, the response body comes back as bytes. - if isinstance(output, str) or isinstance(output, bytes): - if isinstance(output, bytes): - output = output.decode() - - body = json.loads(output) - - if self.prompt_driver.stream: - return TextArtifact(body["outputText"]) - else: - return TextArtifact(body["results"][0]["outputText"]) - else: - raise ValueError("output must be an instance of 'str' or 'bytes'") diff --git a/griptape/drivers/prompt_model/sagemaker_falcon_prompt_model_driver.py b/griptape/drivers/prompt_model/sagemaker_falcon_prompt_model_driver.py deleted file mode 100644 index a5a8a4dc9..000000000 --- a/griptape/drivers/prompt_model/sagemaker_falcon_prompt_model_driver.py +++ /dev/null @@ -1,42 +0,0 @@ -from __future__ import annotations -from attrs import define, field -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack, import_optional_dependency -from griptape.drivers import BasePromptModelDriver -from griptape.tokenizers import HuggingFaceTokenizer - - -@define -class SageMakerFalconPromptModelDriver(BasePromptModelDriver): - DEFAULT_MAX_TOKENS = 600 - - _tokenizer: HuggingFaceTokenizer = field(default=None, kw_only=True) - - @property - def tokenizer(self) -> HuggingFaceTokenizer: - if self._tokenizer is None: - self._tokenizer = HuggingFaceTokenizer( - tokenizer=import_optional_dependency("transformers").AutoTokenizer.from_pretrained("tiiuae/falcon-40b"), - max_output_tokens=self.max_tokens or self.DEFAULT_MAX_TOKENS, - ) - return self._tokenizer - - def prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> str: - return self.prompt_driver.prompt_stack_to_string(prompt_stack) - - def prompt_stack_to_model_params(self, prompt_stack: PromptStack) -> dict: - prompt = self.prompt_stack_to_model_input(prompt_stack) - stop_sequences = self.prompt_driver.tokenizer.stop_sequences - - return { - "max_new_tokens": self.prompt_driver.max_output_tokens(prompt), - "temperature": self.prompt_driver.temperature, - "do_sample": True, - "stop": stop_sequences, - } - - def process_output(self, output: dict | list[dict] | str | bytes) -> TextArtifact: - if isinstance(output, list): - return TextArtifact(output[0]["generated_text"].strip()) - else: - raise ValueError("output must be an instance of 'list'") diff --git a/griptape/drivers/prompt_model/sagemaker_llama_prompt_model_driver.py b/griptape/drivers/prompt_model/sagemaker_llama_prompt_model_driver.py deleted file mode 100644 index 7e934d4a6..000000000 --- a/griptape/drivers/prompt_model/sagemaker_llama_prompt_model_driver.py +++ /dev/null @@ -1,47 +0,0 @@ -from __future__ import annotations -from attrs import define, field -from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack, import_optional_dependency -from griptape.drivers import BasePromptModelDriver -from griptape.tokenizers import HuggingFaceTokenizer - - -@define -class SageMakerLlamaPromptModelDriver(BasePromptModelDriver): - # Default context length for all Llama 3 models is 8K as per https://huggingface.co/blog/llama3 - DEFAULT_MAX_INPUT_TOKENS = 8000 - - _tokenizer: HuggingFaceTokenizer = field(default=None, kw_only=True) - - @property - def tokenizer(self) -> HuggingFaceTokenizer: - if self._tokenizer is None: - self._tokenizer = HuggingFaceTokenizer( - tokenizer=import_optional_dependency("transformers").AutoTokenizer.from_pretrained( - "meta-llama/Meta-Llama-3-8B-Instruct", model_max_length=self.DEFAULT_MAX_INPUT_TOKENS - ), - max_output_tokens=self.max_tokens or self.DEFAULT_MAX_INPUT_TOKENS, - ) - return self._tokenizer - - def prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> str: - return self.tokenizer.tokenizer.apply_chat_template( # pyright: ignore - [{"role": i.role, "content": i.content} for i in prompt_stack.inputs], - tokenize=False, - add_generation_prompt=True, - ) - - def prompt_stack_to_model_params(self, prompt_stack: PromptStack) -> dict: - prompt = self.prompt_driver.prompt_stack_to_string(prompt_stack) - return { - "max_new_tokens": self.prompt_driver.max_output_tokens(prompt), - "temperature": self.prompt_driver.temperature, - "stop": self.tokenizer.tokenizer.eos_token, - } - - def process_output(self, output: dict | list[dict] | str | bytes) -> TextArtifact: - # This output format is specific to the Llama 3 Instruct models when deployed via SageMaker JumpStart. - if isinstance(output, dict): - return TextArtifact(output["generated_text"]) - else: - raise ValueError("Invalid output format.") diff --git a/griptape/engines/query/vector_query_engine.py b/griptape/engines/query/vector_query_engine.py index adfa4b2db..24338b348 100644 --- a/griptape/engines/query/vector_query_engine.py +++ b/griptape/engines/query/vector_query_engine.py @@ -49,12 +49,14 @@ def query( ) user_message = self.user_template_generator.render(query=query) - message_token_count = self.prompt_driver.token_count( - PromptStack( - inputs=[ - PromptStack.Input(system_message, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(user_message, role=PromptStack.USER_ROLE), - ] + message_token_count = self.prompt_driver.tokenizer.count_input_tokens_left( + self.prompt_driver.prompt_stack_to_string( + PromptStack( + inputs=[ + PromptStack.Input(system_message, role=PromptStack.SYSTEM_ROLE), + PromptStack.Input(user_message, role=PromptStack.USER_ROLE), + ] + ) ) ) diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 0da99cb0a..9d3e8db78 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -13,7 +13,8 @@ class PromptSummaryEngine(BaseSummaryEngine): chunk_joiner: str = field(default="\n\n", kw_only=True) max_token_multiplier: float = field(default=0.5, kw_only=True) - template_generator: J2 = field(default=Factory(lambda: J2("engines/summary/prompt_summary.j2")), kw_only=True) + system_template_generator: J2 = field(default=Factory(lambda: J2("engines/summary/system.j2")), kw_only=True) + user_template_generator: J2 = field(default=Factory(lambda: J2("engines/summary/user.j2")), kw_only=True) prompt_driver: BasePromptDriver = field(kw_only=True) chunker: BaseChunker = field( default=Factory( @@ -49,25 +50,38 @@ def summarize_artifacts_rec( ) -> TextArtifact: artifacts_text = self.chunk_joiner.join([a.to_text() for a in artifacts]) - full_text = self.template_generator.render( - summary=summary, text=artifacts_text, rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets) + system_prompt = self.system_template_generator.render( + summary=summary, rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets) ) - if self.prompt_driver.tokenizer.count_input_tokens_left(full_text) >= self.min_response_tokens: + user_prompt = self.user_template_generator.render(text=artifacts_text) + + if ( + self.prompt_driver.tokenizer.count_input_tokens_left(user_prompt + system_prompt) + >= self.min_response_tokens + ): return self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(full_text, role=PromptStack.USER_ROLE)]) + PromptStack( + inputs=[ + PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), + PromptStack.Input(user_prompt, role=PromptStack.USER_ROLE), + ] + ) ) else: chunks = self.chunker.chunk(artifacts_text) - partial_text = self.template_generator.render( - summary=summary, text=chunks[0].value, rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets) - ) + partial_text = self.user_template_generator.render(text=chunks[0].value) return self.summarize_artifacts_rec( chunks[1:], self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(partial_text, role=PromptStack.USER_ROLE)]) + PromptStack( + inputs=[ + PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), + PromptStack.Input(partial_text, role=PromptStack.USER_ROLE), + ] + ) ).value, rulesets=rulesets, ) diff --git a/griptape/loaders/web_loader.py b/griptape/loaders/web_loader.py index f8862f7cd..64a52b65f 100644 --- a/griptape/loaders/web_loader.py +++ b/griptape/loaders/web_loader.py @@ -13,5 +13,8 @@ class WebLoader(BaseTextLoader): ) def load(self, source: str, *args, **kwargs) -> ErrorArtifact | list[TextArtifact]: - single_chunk_text_artifact = self.web_scraper_driver.scrape_url(source) - return self._text_to_artifacts(single_chunk_text_artifact.value) + try: + single_chunk_text_artifact = self.web_scraper_driver.scrape_url(source) + return self._text_to_artifacts(single_chunk_text_artifact.value) + except Exception as e: + return ErrorArtifact(f"Error loading from source: {source}", exception=e) diff --git a/griptape/memory/structure/base_conversation_memory.py b/griptape/memory/structure/base_conversation_memory.py index 6db05c92c..f8cc51743 100644 --- a/griptape/memory/structure/base_conversation_memory.py +++ b/griptape/memory/structure/base_conversation_memory.py @@ -45,3 +45,52 @@ def try_add_run(self, run: Run) -> None: ... @abstractmethod def to_prompt_stack(self, last_n: Optional[int] = None) -> PromptStack: ... + + def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = None) -> PromptStack: + """Add the Conversation Memory runs to the Prompt Stack by modifying the inputs in place. + + If autoprune is enabled, this will fit as many Conversation Memory runs into the Prompt Stack + as possible without exceeding the token limit. + + Args: + prompt_stack: The Prompt Stack to add the Conversation Memory to. + index: Optional index to insert the Conversation Memory runs at. + Defaults to appending to the end of the Prompt Stack. + """ + num_runs_to_fit_in_prompt = len(self.runs) + + if self.autoprune and hasattr(self, "structure"): + should_prune = True + prompt_driver = self.structure.config.prompt_driver + temp_stack = PromptStack() + + # Try to determine how many Conversation Memory runs we can + # fit into the Prompt Stack without exceeding the token limit. + while should_prune and num_runs_to_fit_in_prompt > 0: + temp_stack.inputs = prompt_stack.inputs.copy() + + # Add n runs from Conversation Memory. + # Where we insert into the Prompt Stack doesn't matter here + # since we only care about the total token count. + memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).inputs + temp_stack.inputs.extend(memory_inputs) + + # Convert the prompt stack into tokens left. + tokens_left = prompt_driver.tokenizer.count_input_tokens_left( + prompt_driver.prompt_stack_to_string(temp_stack) + ) + if tokens_left > 0: + # There are still tokens left, no need to prune. + should_prune = False + else: + # There were not any tokens left, prune one run and try again. + num_runs_to_fit_in_prompt -= 1 + + if num_runs_to_fit_in_prompt: + memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).inputs + if index: + prompt_stack.inputs[index:index] = memory_inputs + else: + prompt_stack.inputs.extend(memory_inputs) + + return prompt_stack diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 79ae5e51f..6ba23d6fe 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -103,13 +103,14 @@ def _resolve_types(cls, attrs_cls: type) -> None: from griptape.utils.import_utils import import_optional_dependency, is_dependency_installed # These modules are required to avoid `NameError`s when resolving types. - from griptape.drivers import BaseConversationMemoryDriver, BasePromptDriver, BasePromptModelDriver + from griptape.drivers import BaseConversationMemoryDriver, BasePromptDriver from griptape.structures import Structure from griptape.utils import PromptStack from griptape.tokenizers.base_tokenizer import BaseTokenizer from typing import Any boto3 = import_optional_dependency("boto3") if is_dependency_installed("boto3") else Any + Client = import_optional_dependency("cohere").Client if is_dependency_installed("cohere") else Any attrs.resolve_types( attrs_cls, @@ -120,8 +121,8 @@ def _resolve_types(cls, attrs_cls: type) -> None: "BaseConversationMemoryDriver": BaseConversationMemoryDriver, "BasePromptDriver": BasePromptDriver, "BaseTokenizer": BaseTokenizer, - "BasePromptModelDriver": BasePromptModelDriver, "boto3": boto3, + "Client": Client, }, ) diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 79b831f63..d0446aff0 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -47,13 +47,9 @@ def add_tasks(self, *tasks: BaseTask) -> list[BaseTask]: return super().add_tasks(*tasks) def try_run(self, *args) -> Agent: - self._execution_args = args - - self.task.reset() - self.task.execute() - if self.conversation_memory: + if self.conversation_memory and self.output is not None: if isinstance(self.task.input, tuple): input_text = self.task.input[0].to_text() else: diff --git a/griptape/structures/pipeline.py b/griptape/structures/pipeline.py index 00c5f1d09..d5724244e 100644 --- a/griptape/structures/pipeline.py +++ b/griptape/structures/pipeline.py @@ -43,19 +43,15 @@ def insert_task(self, parent_task: BaseTask, task: BaseTask) -> BaseTask: return task def try_run(self, *args) -> Pipeline: - self._execution_args = args - - [task.reset() for task in self.tasks] - self.__run_from_task(self.input_task) - if self.conversation_memory: + if self.conversation_memory and self.output is not None: if isinstance(self.input_task.input, tuple): input_text = self.input_task.input[0].to_text() else: input_text = self.input_task.input.to_text() - run = Run(input=input_text, output=self.output_task.output.to_text()) + run = Run(input=input_text, output=self.output.to_text()) self.conversation_memory.add_run(run) diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 8b71dd905..78dd69633 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -9,7 +9,7 @@ from attrs import Factory, define, field from rich.logging import RichHandler -from griptape.artifacts import BlobArtifact, TextArtifact +from griptape.artifacts import BlobArtifact, TextArtifact, BaseArtifact from griptape.config import BaseStructureConfig, OpenAiStructureConfig, StructureConfig from griptape.drivers import BaseEmbeddingDriver, BasePromptDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.drivers.vector.local_vector_store_driver import LocalVectorStoreDriver @@ -127,13 +127,17 @@ def input_task(self) -> Optional[BaseTask]: def output_task(self) -> Optional[BaseTask]: return self.tasks[-1] if self.tasks else None + @property + def output(self) -> Optional[BaseArtifact]: + return self.output_task.output if self.output_task is not None else None + @property def finished_tasks(self) -> list[BaseTask]: return [s for s in self.tasks if s.is_finished()] @property def default_config(self) -> BaseStructureConfig: - if self.prompt_driver is not None or self.embedding_driver is not None: + if self.prompt_driver is not None or self.embedding_driver is not None or self.stream is not None: config = StructureConfig() if self.prompt_driver is None: @@ -209,13 +213,39 @@ def publish_event(self, event: BaseEvent, flush: bool = False) -> None: def context(self, task: BaseTask) -> dict[str, Any]: return {"args": self.execution_args, "structure": self} - def before_run(self) -> None: + def resolve_relationships(self) -> None: + task_by_id = {task.id: task for task in self.tasks} + + for task in self.tasks: + # Ensure parents include this task as a child + for parent_id in task.parent_ids: + if parent_id not in task_by_id: + raise ValueError(f"Task with id {parent_id} doesn't exist.") + parent = task_by_id[parent_id] + if task.id not in parent.child_ids: + parent.child_ids.append(task.id) + + # Ensure children include this task as a parent + for child_id in task.child_ids: + if child_id not in task_by_id: + raise ValueError(f"Task with id {child_id} doesn't exist.") + child = task_by_id[child_id] + if task.id not in child.parent_ids: + child.parent_ids.append(task.id) + + def before_run(self, args: Any) -> None: + self._execution_args = args + + [task.reset() for task in self.tasks] + self.publish_event( StartStructureRunEvent( structure_id=self.id, input_task_input=self.input_task.input, input_task_output=self.input_task.output ) ) + self.resolve_relationships() + def after_run(self) -> None: self.publish_event( FinishStructureRunEvent( @@ -230,7 +260,7 @@ def after_run(self) -> None: def add_task(self, task: BaseTask) -> BaseTask: ... def run(self, *args) -> Structure: - self.before_run() + self.before_run(args) result = self.try_run(*args) diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index e60efa425..6552fba89 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -1,7 +1,7 @@ from __future__ import annotations import concurrent.futures as futures from graphlib import TopologicalSorter -from typing import Any +from typing import Any, Optional from attrs import define, field, Factory from griptape.artifacts import ErrorArtifact from griptape.structures import Structure @@ -13,13 +13,13 @@ class Workflow(Structure): futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + @property + def output_task(self) -> Optional[BaseTask]: + return self.order_tasks()[-1] if self.tasks else None + def add_task(self, task: BaseTask) -> BaseTask: task.preprocess(self) - if self.output_task: - self.output_task.child_ids.append(task.id) - task.parent_ids.append(self.output_task.id) - self.tasks.append(task) return task @@ -77,6 +77,7 @@ def insert_task( if parent_task.id in child_task.parent_ids: child_task.parent_ids.remove(parent_task.id) + last_parent_index = -1 for parent_task in parent_tasks: # Link the new task to the parent task if parent_task.id not in task.parent_ids: @@ -85,17 +86,20 @@ def insert_task( parent_task.child_ids.append(task.id) parent_index = self.tasks.index(parent_task) - self.tasks.insert(parent_index + 1, task) + if parent_index > last_parent_index: + last_parent_index = parent_index + + # Insert the new task once, just after the last parent task + self.tasks.insert(last_parent_index + 1, task) return task def try_run(self, *args) -> Workflow: - self._execution_args = args - ordered_tasks = self.order_tasks() exit_loop = False while not self.is_finished() and not exit_loop: futures_list = {} + ordered_tasks = self.order_tasks() for task in ordered_tasks: if task.can_execute(): @@ -109,7 +113,7 @@ def try_run(self, *args) -> Workflow: break - if self.conversation_memory: + if self.conversation_memory and self.output is not None: if isinstance(self.input_task.input, tuple): input_text = self.input_task.input[0].to_text() else: @@ -126,9 +130,8 @@ def context(self, task: BaseTask) -> dict[str, Any]: context.update( { - "parent_outputs": { - parent.id: parent.output.to_text() if parent.output else "" for parent in task.parents - }, + "parent_outputs": task.parent_outputs, + "parents_output_text": task.parents_output_text, "parents": {parent.id: parent for parent in task.parents}, "children": {child.id: child for child in task.children}, } diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index d47d1df32..1546a825d 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -101,7 +101,13 @@ def run(self) -> BaseArtifact: else: results = self.execute_actions(self.actions) - self.output = ListArtifact([TextArtifact(name=f"{r[0]} output", value=r[1].to_text()) for r in results]) + actions_output = [] + for result in results: + tag, output = result + output.name = f"{tag} output" + + actions_output.append(output) + self.output = ListArtifact(actions_output) except Exception as e: self.structure.logger.error(f"Subtask {self.id}\n{e}", exc_info=True) @@ -172,24 +178,6 @@ def actions_to_dicts(self) -> list[dict]: def actions_to_json(self) -> str: return json.dumps(self.actions_to_dicts()) - def add_child(self, child: ActionsSubtask) -> ActionsSubtask: - if child.id not in self.child_ids: - self.child_ids.append(child.id) - - if self.id not in child.parent_ids: - child.parent_ids.append(self.id) - - return child - - def add_parent(self, parent: ActionsSubtask) -> ActionsSubtask: - if parent.id not in self.parent_ids: - self.parent_ids.append(parent.id) - - if self.id not in parent.child_ids: - parent.child_ids.append(self.id) - - return parent - def __init_from_prompt(self, value: str) -> None: thought_matches = re.findall(self.THOUGHT_PATTERN, value, re.MULTILINE) actions_matches = re.findall(self.ACTIONS_PATTERN, value, re.DOTALL) diff --git a/griptape/tasks/audio_transcription_task.py b/griptape/tasks/audio_transcription_task.py index c75faa0d4..57dbf6782 100644 --- a/griptape/tasks/audio_transcription_task.py +++ b/griptape/tasks/audio_transcription_task.py @@ -1,37 +1,18 @@ from __future__ import annotations -from abc import ABC -from typing import Callable - from attrs import define, field -from griptape.artifacts.audio_artifact import AudioArtifact from griptape.engines import AudioTranscriptionEngine from griptape.artifacts import TextArtifact -from griptape.mixins import RuleMixin -from griptape.tasks import BaseTask +from griptape.tasks.base_audio_input_task import BaseAudioInputTask @define -class AudioTranscriptionTask(RuleMixin, BaseTask, ABC): - _input: AudioArtifact | Callable[[BaseTask], AudioArtifact] = field() +class AudioTranscriptionTask(BaseAudioInputTask): _audio_transcription_engine: AudioTranscriptionEngine = field( default=None, kw_only=True, alias="audio_transcription_engine" ) - @property - def input(self) -> AudioArtifact: - if isinstance(self._input, AudioArtifact): - return self._input - elif isinstance(self._input, Callable): - return self._input(self) - else: - raise ValueError("Input must be an AudioArtifact.") - - @input.setter - def input(self, value: AudioArtifact | Callable[[BaseTask], AudioArtifact]) -> None: - self._input = value - @property def audio_transcription_engine(self) -> AudioTranscriptionEngine: if self._audio_transcription_engine is None: diff --git a/griptape/tasks/base_audio_generation_task.py b/griptape/tasks/base_audio_generation_task.py index d401af0a5..71c2fbdf4 100644 --- a/griptape/tasks/base_audio_generation_task.py +++ b/griptape/tasks/base_audio_generation_task.py @@ -9,4 +9,13 @@ @define -class BaseAudioGenerationTask(BlobArtifactFileOutputMixin, RuleMixin, BaseTask, ABC): ... +class BaseAudioGenerationTask(BlobArtifactFileOutputMixin, RuleMixin, BaseTask, ABC): + def before_run(self) -> None: + super().before_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nInput: {self.input.to_text()}") + + def after_run(self) -> None: + super().after_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nOutput: {self.output.to_text()}") diff --git a/griptape/tasks/base_audio_input_task.py b/griptape/tasks/base_audio_input_task.py new file mode 100644 index 000000000..0991a6014 --- /dev/null +++ b/griptape/tasks/base_audio_input_task.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from abc import ABC +from typing import Callable + +from attrs import define, field + +from griptape.artifacts.audio_artifact import AudioArtifact +from griptape.mixins import RuleMixin +from griptape.tasks import BaseTask + + +@define +class BaseAudioInputTask(RuleMixin, BaseTask, ABC): + _input: AudioArtifact | Callable[[BaseTask], AudioArtifact] = field(alias="input") + + @property + def input(self) -> AudioArtifact: + if isinstance(self._input, AudioArtifact): + return self._input + elif isinstance(self._input, Callable): + return self._input(self) + else: + raise ValueError("Input must be an AudioArtifact.") + + @input.setter + def input(self, value: AudioArtifact | Callable[[BaseTask], AudioArtifact]) -> None: + self._input = value + + def before_run(self) -> None: + super().before_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nInput: {self.input.to_text()}") + + def after_run(self) -> None: + super().after_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nOutput: {self.output.to_text()}") diff --git a/griptape/tasks/base_task.py b/griptape/tasks/base_task.py index 771fe4dc8..8a45cb14e 100644 --- a/griptape/tasks/base_task.py +++ b/griptape/tasks/base_task.py @@ -47,6 +47,14 @@ def parents(self) -> list[BaseTask]: def children(self) -> list[BaseTask]: return [self.structure.find_task(child_id) for child_id in self.child_ids] + @property + def parent_outputs(self) -> dict[str, str]: + return {parent.id: parent.output.to_text() if parent.output else "" for parent in self.parents} + + @property + def parents_output_text(self) -> str: + return "\n".join([parent.output.to_text() for parent in self.parents if parent.output]) + @property def meta_memories(self) -> list[BaseMetaEntry]: if self.structure and self.structure.meta_memory: @@ -60,6 +68,26 @@ def meta_memories(self) -> list[BaseMetaEntry]: def __str__(self) -> str: return str(self.output.value) + def add_parents(self, parents: list[str | BaseTask]) -> None: + for parent in parents: + self.add_parent(parent) + + def add_parent(self, parent: str | BaseTask) -> None: + parent_id = parent if isinstance(parent, str) else parent.id + + if parent_id not in self.parent_ids: + self.parent_ids.append(parent_id) + + def add_children(self, children: list[str | BaseTask]) -> None: + for child in children: + self.add_child(child) + + def add_child(self, child: str | BaseTask) -> None: + child_id = child if isinstance(child, str) else child.id + + if child_id not in self.child_ids: + self.child_ids.append(child_id) + def preprocess(self, structure: Structure) -> BaseTask: self.structure = structure diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index 75051db74..694a5050d 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -34,7 +34,7 @@ def prompt_stack(self) -> PromptStack: if memory: # inserting at index 1 to place memory right after system prompt - stack.add_conversation_memory(memory, 1) + memory.add_to_prompt_stack(stack, 1) return stack diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index ed787aa45..c99f9e23f 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -21,6 +21,9 @@ @define class ToolkitTask(PromptTask, ActionsSubtaskOriginMixin): DEFAULT_MAX_STEPS = 20 + # Stop sequence for chain-of-thought in the framework. Using this "token-like" string to make it more unique, + # so that it doesn't trigger on accident. + RESPONSE_STOP_SEQUENCE = "<|Response|>" tools: list[BaseTool] = field(factory=list, kw_only=True) max_subtasks: int = field(default=DEFAULT_MAX_STEPS, kw_only=True) @@ -32,6 +35,7 @@ class ToolkitTask(PromptTask, ActionsSubtaskOriginMixin): generate_user_subtask_template: Callable[[ActionsSubtask], str] = field( default=Factory(lambda self: self.default_user_subtask_template_generator, takes_self=True), kw_only=True ) + response_stop_sequence: str = field(default=RESPONSE_STOP_SEQUENCE, kw_only=True) def __attrs_post_init__(self) -> None: if self.task_memory: @@ -74,7 +78,7 @@ def prompt_stack(self) -> PromptStack: if memory: # inserting at index 1 to place memory right after system prompt - stack.add_conversation_memory(memory, 1) + memory.add_to_prompt_stack(stack, 1) return stack @@ -95,17 +99,17 @@ def default_system_template_generator(self, _: PromptTask) -> str: action_names=str.join(", ", [tool.name for tool in self.tools]), actions_schema=utils.minify_json(json.dumps(schema)), meta_memory=J2("memory/meta/meta_memory.j2").render(meta_memories=self.meta_memories), - stop_sequence=utils.constants.RESPONSE_STOP_SEQUENCE, + stop_sequence=self.response_stop_sequence, ) def default_assistant_subtask_template_generator(self, subtask: ActionsSubtask) -> str: return J2("tasks/toolkit_task/assistant_subtask.j2").render( - stop_sequence=utils.constants.RESPONSE_STOP_SEQUENCE, subtask=subtask + stop_sequence=self.response_stop_sequence, subtask=subtask ) def default_user_subtask_template_generator(self, subtask: ActionsSubtask) -> str: return J2("tasks/toolkit_task/user_subtask.j2").render( - stop_sequence=utils.constants.RESPONSE_STOP_SEQUENCE, subtask=subtask + stop_sequence=self.response_stop_sequence, subtask=subtask ) def actions_schema(self) -> Schema: @@ -126,6 +130,7 @@ def run(self) -> BaseArtifact: self.subtasks.clear() + self.prompt_driver.tokenizer.stop_sequences.extend([self.response_stop_sequence]) subtask = self.add_subtask(ActionsSubtask(self.prompt_driver.run(prompt_stack=self.prompt_stack).to_text())) while True: @@ -161,6 +166,7 @@ def add_subtask(self, subtask: ActionsSubtask) -> ActionsSubtask: if len(self.subtasks) > 0: self.subtasks[-1].add_child(subtask) + subtask.add_parent(self.subtasks[-1]) self.subtasks.append(subtask) diff --git a/griptape/templates/engines/summary/prompt_summary.j2 b/griptape/templates/engines/summary/prompt_summary.j2 deleted file mode 100644 index 717810de6..000000000 --- a/griptape/templates/engines/summary/prompt_summary.j2 +++ /dev/null @@ -1,27 +0,0 @@ -{% if summary %} -Current text summary: """ -{{ summary }} -""" - -Rewrite the current text summary to include the following additional text: """ -{{ text }} -""" -{% if rulesets %} - -{{ rulesets }} -{% endif %} - -Rewritten summary: -{% else %} - -Summarize the following text: """ -{{ text }} -""" - -{% if rulesets %} - -{{ rulesets }} -{% endif %} - -Summary: -{% endif %} diff --git a/griptape/templates/engines/summary/system.j2 b/griptape/templates/engines/summary/system.j2 new file mode 100644 index 000000000..b5e132aa0 --- /dev/null +++ b/griptape/templates/engines/summary/system.j2 @@ -0,0 +1,14 @@ +You are an expert in text summarization. +{% if rulesets %} + +{{ rulesets }} + +{% endif %} + +{% if summary %} +Use the current text summary to help summarize the additional text. +Current text summary: """ +{{ summary }} +""" + +{% endif %} diff --git a/griptape/templates/engines/summary/user.j2 b/griptape/templates/engines/summary/user.j2 new file mode 100644 index 000000000..d6a40e412 --- /dev/null +++ b/griptape/templates/engines/summary/user.j2 @@ -0,0 +1,5 @@ +Summarize the following text: """ +{{ text }} +""" + +Summary: diff --git a/griptape/templates/tasks/tool_task/system.j2 b/griptape/templates/tasks/tool_task/system.j2 index eaf858037..7a802d989 100644 --- a/griptape/templates/tasks/tool_task/system.j2 +++ b/griptape/templates/tasks/tool_task/system.j2 @@ -1,5 +1,4 @@ -When appropriate, respond to requests by using the following Action Schema. Your response should be a plain JSON object that successfully validates against the schema. The schema is provided below. If you can't use the Action Schema, say "I don't know how to respond." - +You must respond to requests by using the following Action Schema. Your response should be a plain JSON object that successfully validates against the schema. The schema is provided below. If you can't use the Action Schema, say "I don't know how to respond." Action Schema: {{ action_schema }} {% if meta_memory %} diff --git a/griptape/tokenizers/__init__.py b/griptape/tokenizers/__init__.py index b116f9fb0..03b0aefe5 100644 --- a/griptape/tokenizers/__init__.py +++ b/griptape/tokenizers/__init__.py @@ -3,15 +3,11 @@ from griptape.tokenizers.cohere_tokenizer import CohereTokenizer from griptape.tokenizers.huggingface_tokenizer import HuggingFaceTokenizer from griptape.tokenizers.anthropic_tokenizer import AnthropicTokenizer -from griptape.tokenizers.bedrock_titan_tokenizer import BedrockTitanTokenizer -from griptape.tokenizers.bedrock_cohere_tokenizer import BedrockCohereTokenizer -from griptape.tokenizers.bedrock_jurassic_tokenizer import BedrockJurassicTokenizer -from griptape.tokenizers.bedrock_claude_tokenizer import BedrockClaudeTokenizer -from griptape.tokenizers.bedrock_llama_tokenizer import BedrockLlamaTokenizer from griptape.tokenizers.google_tokenizer import GoogleTokenizer from griptape.tokenizers.voyageai_tokenizer import VoyageAiTokenizer from griptape.tokenizers.simple_tokenizer import SimpleTokenizer from griptape.tokenizers.dummy_tokenizer import DummyTokenizer +from griptape.tokenizers.amazon_bedrock_tokenizer import AmazonBedrockTokenizer __all__ = [ @@ -20,13 +16,9 @@ "CohereTokenizer", "HuggingFaceTokenizer", "AnthropicTokenizer", - "BedrockTitanTokenizer", - "BedrockCohereTokenizer", - "BedrockJurassicTokenizer", - "BedrockClaudeTokenizer", - "BedrockLlamaTokenizer", "GoogleTokenizer", "VoyageAiTokenizer", "SimpleTokenizer", "DummyTokenizer", + "AmazonBedrockTokenizer", ] diff --git a/griptape/tokenizers/amazon_bedrock_tokenizer.py b/griptape/tokenizers/amazon_bedrock_tokenizer.py new file mode 100644 index 000000000..670b5739a --- /dev/null +++ b/griptape/tokenizers/amazon_bedrock_tokenizer.py @@ -0,0 +1,40 @@ +from __future__ import annotations +from attrs import define, field +from griptape.tokenizers.base_tokenizer import BaseTokenizer + + +@define() +class AmazonBedrockTokenizer(BaseTokenizer): + MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = { + "anthropic.claude-3": 200000, + "anthropic.claude-v2:1": 200000, + "anthropic.claude": 100000, + "cohere.command-r": 128000, + "cohere.embed": 512, + "cohere.command": 4000, + "cohere": 1024, + "ai21": 8192, + "meta-llama3": 8000, + "meta-llama2": 4096, + "mistral": 32000, + "amazon": 4096, + } + MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = { + "anthropic.claude": 4096, + "cohere": 4096, + "ai21.j2": 8191, + "meta": 2048, + "amazon.titan-text-lite": 4096, + "amazon.titan-text-express": 8192, + "amazon.titan-text-premier": 3072, + "amazon": 4096, + "mistral": 8192, + } + + model: str = field(kw_only=True) + characters_per_token: int = field(default=4, kw_only=True) + + def count_tokens(self, text: str) -> int: + num_tokens = (len(text) + self.characters_per_token - 1) // self.characters_per_token + + return num_tokens diff --git a/griptape/tokenizers/anthropic_tokenizer.py b/griptape/tokenizers/anthropic_tokenizer.py index 577df7b93..f5fabab0e 100644 --- a/griptape/tokenizers/anthropic_tokenizer.py +++ b/griptape/tokenizers/anthropic_tokenizer.py @@ -17,8 +17,5 @@ class AnthropicTokenizer(BaseTokenizer): default=Factory(lambda: import_optional_dependency("anthropic").Anthropic()), kw_only=True ) - def count_tokens(self, text: str | list) -> int: - if isinstance(text, str): - return self.client.count_tokens(text) - else: - raise ValueError("Text must be a string.") + def count_tokens(self, text: str) -> int: + return self.client.count_tokens(text) diff --git a/griptape/tokenizers/base_tokenizer.py b/griptape/tokenizers/base_tokenizer.py index 179d2fb59..474ccbaa5 100644 --- a/griptape/tokenizers/base_tokenizer.py +++ b/griptape/tokenizers/base_tokenizer.py @@ -1,27 +1,30 @@ from __future__ import annotations -from abc import ABC, abstractmethod +import logging +from abc import ABC from attrs import define, field, Factory -from griptape import utils @define() class BaseTokenizer(ABC): + DEFAULT_MAX_INPUT_TOKENS = 4096 + DEFAULT_MAX_OUTPUT_TOKENS = 1000 MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = {} MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {} model: str = field(kw_only=True) - stop_sequences: list[str] = field(default=Factory(lambda: [utils.constants.RESPONSE_STOP_SEQUENCE]), kw_only=True) + stop_sequences: list[str] = field(default=Factory(list), kw_only=True) max_input_tokens: int = field(kw_only=True, default=None) max_output_tokens: int = field(kw_only=True, default=None) def __attrs_post_init__(self) -> None: - if self.max_input_tokens is None: - self.max_input_tokens = self._default_max_input_tokens() + if hasattr(self, "model"): + if self.max_input_tokens is None: + self.max_input_tokens = self._default_max_input_tokens() - if self.max_output_tokens is None: - self.max_output_tokens = self._default_max_output_tokens() + if self.max_output_tokens is None: + self.max_output_tokens = self._default_max_output_tokens() - def count_input_tokens_left(self, text: str | list) -> int: + def count_input_tokens_left(self, text: str) -> int: diff = self.max_input_tokens - self.count_tokens(text) if diff > 0: @@ -29,7 +32,7 @@ def count_input_tokens_left(self, text: str | list) -> int: else: return 0 - def count_output_tokens_left(self, text: str | list) -> int: + def count_output_tokens_left(self, text: str) -> int: diff = self.max_output_tokens - self.count_tokens(text) if diff > 0: @@ -37,14 +40,16 @@ def count_output_tokens_left(self, text: str | list) -> int: else: return 0 - @abstractmethod - def count_tokens(self, text: str | list[dict]) -> int: ... + def count_tokens(self, text: str) -> int: ... def _default_max_input_tokens(self) -> int: tokens = next((v for k, v in self.MODEL_PREFIXES_TO_MAX_INPUT_TOKENS.items() if self.model.startswith(k)), None) if tokens is None: - raise ValueError(f"Unknown model default max input tokens: {self.model}") + logging.warning( + f"Model {self.model} not found in MODEL_PREFIXES_TO_MAX_INPUT_TOKENS, using default value of {self.DEFAULT_MAX_INPUT_TOKENS}." + ) + return self.DEFAULT_MAX_INPUT_TOKENS else: return tokens @@ -54,6 +59,9 @@ def _default_max_output_tokens(self) -> int: ) if tokens is None: - raise ValueError(f"Unknown model for default max output tokens: {self.model}") + logging.warning( + f"Model {self.model} not found in MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS, using default value of {self.DEFAULT_MAX_OUTPUT_TOKENS}." + ) + return self.DEFAULT_MAX_OUTPUT_TOKENS else: return tokens diff --git a/griptape/tokenizers/bedrock_claude_tokenizer.py b/griptape/tokenizers/bedrock_claude_tokenizer.py deleted file mode 100644 index d44116e2c..000000000 --- a/griptape/tokenizers/bedrock_claude_tokenizer.py +++ /dev/null @@ -1,12 +0,0 @@ -from attrs import define -from griptape.tokenizers import AnthropicTokenizer - - -@define() -class BedrockClaudeTokenizer(AnthropicTokenizer): - MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = { - "anthropic.claude-3": 200000, - "anthropic.claude-v2:1": 200000, - "anthropic.claude": 100000, - } - MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {"anthropic.claude": 4096} diff --git a/griptape/tokenizers/bedrock_cohere_tokenizer.py b/griptape/tokenizers/bedrock_cohere_tokenizer.py deleted file mode 100644 index 44ccb4ac6..000000000 --- a/griptape/tokenizers/bedrock_cohere_tokenizer.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import annotations -from attrs import define, field -from .simple_tokenizer import SimpleTokenizer - - -@define() -class BedrockCohereTokenizer(SimpleTokenizer): - # https://docs.aws.amazon.com/bedrock/latest/userguide/model-parameters-embed.html - DEFAULT_CHARACTERS_PER_TOKEN = 4 - MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = {"cohere": 1024} - MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {"cohere": 4096} - - model: str = field(kw_only=True) - characters_per_token: int = field(default=DEFAULT_CHARACTERS_PER_TOKEN, kw_only=True) diff --git a/griptape/tokenizers/bedrock_jurassic_tokenizer.py b/griptape/tokenizers/bedrock_jurassic_tokenizer.py deleted file mode 100644 index 7511138b3..000000000 --- a/griptape/tokenizers/bedrock_jurassic_tokenizer.py +++ /dev/null @@ -1,20 +0,0 @@ -from __future__ import annotations -from attrs import define, field, Factory -from .simple_tokenizer import SimpleTokenizer - - -@define() -class BedrockJurassicTokenizer(SimpleTokenizer): - DEFAULT_CHARACTERS_PER_TOKEN = 6 # https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html#model-customization-prepare-finetuning - MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = {"ai21": 8192} - MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = { - "ai21.j2-mid-v1": 8191, - "ai21.j2-ultra-v1": 8191, - "ai21.j2-large-v1": 8191, - "ai21": 2048, - } - - model: str = field(kw_only=True) - characters_per_token: int = field( - default=Factory(lambda self: self.DEFAULT_CHARACTERS_PER_TOKEN, takes_self=True), kw_only=True - ) diff --git a/griptape/tokenizers/bedrock_llama_tokenizer.py b/griptape/tokenizers/bedrock_llama_tokenizer.py deleted file mode 100644 index e7d1ec829..000000000 --- a/griptape/tokenizers/bedrock_llama_tokenizer.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import annotations -from attrs import define, field -from .simple_tokenizer import SimpleTokenizer - - -@define() -class BedrockLlamaTokenizer(SimpleTokenizer): - DEFAULT_CHARACTERS_PER_TOKEN = 6 # https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html#model-customization-prepare-finetuning - MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = {"meta": 2048} - MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {"meta": 2048} - - model: str = field(kw_only=True) - characters_per_token: int = field(default=DEFAULT_CHARACTERS_PER_TOKEN, kw_only=True) - stop_sequences: list[str] = field(factory=list, kw_only=True) diff --git a/griptape/tokenizers/bedrock_titan_tokenizer.py b/griptape/tokenizers/bedrock_titan_tokenizer.py deleted file mode 100644 index 0d8ba0273..000000000 --- a/griptape/tokenizers/bedrock_titan_tokenizer.py +++ /dev/null @@ -1,14 +0,0 @@ -from __future__ import annotations -from attrs import define, field, Factory -from .simple_tokenizer import SimpleTokenizer - - -@define() -class BedrockTitanTokenizer(SimpleTokenizer): - DEFAULT_CHARACTERS_PER_TOKEN = 6 # https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html#model-customization-prepare-finetuning - MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = {"amazon": 4096} - MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {"amazon": 8000} - - model: str = field(kw_only=True) - characters_per_token: int = field(default=DEFAULT_CHARACTERS_PER_TOKEN, kw_only=True) - stop_sequences: list[str] = field(default=Factory(lambda: ["User:"]), kw_only=True) diff --git a/griptape/tokenizers/cohere_tokenizer.py b/griptape/tokenizers/cohere_tokenizer.py index 0a3c6a236..ae3bddd80 100644 --- a/griptape/tokenizers/cohere_tokenizer.py +++ b/griptape/tokenizers/cohere_tokenizer.py @@ -9,13 +9,10 @@ @define() class CohereTokenizer(BaseTokenizer): - MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = {"command": 4096} - MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {"command": 4096} + MODEL_PREFIXES_TO_MAX_INPUT_TOKENS = {"command-r": 128000, "command": 4096, "embed": 512} + MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {"command": 4096, "embed": 512} client: Client = field(kw_only=True) - def count_tokens(self, text: str | list) -> int: - if isinstance(text, str): - return len(self.client.tokenize(text=text, model=self.model).tokens) - else: - raise ValueError("Text must be a string.") + def count_tokens(self, text: str) -> int: + return len(self.client.tokenize(text=text, model=self.model).tokens) diff --git a/griptape/tokenizers/dummy_tokenizer.py b/griptape/tokenizers/dummy_tokenizer.py index 74f6d104c..a36d0343e 100644 --- a/griptape/tokenizers/dummy_tokenizer.py +++ b/griptape/tokenizers/dummy_tokenizer.py @@ -1,14 +1,15 @@ from __future__ import annotations from attrs import define, field +from typing import Optional from griptape.exceptions import DummyException from griptape.tokenizers import BaseTokenizer @define class DummyTokenizer(BaseTokenizer): - model: None = field(init=False, default=None, kw_only=True) + model: Optional[str] = field(default=None, kw_only=True) max_input_tokens: int = field(init=False, default=0, kw_only=True) max_output_tokens: int = field(init=False, default=0, kw_only=True) - def count_tokens(self, text: str | list) -> int: + def count_tokens(self, text: str) -> int: raise DummyException(__class__.__name__, "count_tokens") diff --git a/griptape/tokenizers/google_tokenizer.py b/griptape/tokenizers/google_tokenizer.py index 55942f597..f99a0682f 100644 --- a/griptape/tokenizers/google_tokenizer.py +++ b/griptape/tokenizers/google_tokenizer.py @@ -18,11 +18,8 @@ class GoogleTokenizer(BaseTokenizer): default=Factory(lambda self: self._default_model_client(), takes_self=True), kw_only=True ) - def count_tokens(self, text: str | list) -> int: - if isinstance(text, str) or isinstance(text, list): - return self.model_client.count_tokens(text).total_tokens - else: - raise ValueError("Text must be a string or a list.") + def count_tokens(self, text: str) -> int: + return self.model_client.count_tokens(text).total_tokens def _default_model_client(self) -> GenerativeModel: genai = import_optional_dependency("google.generativeai") diff --git a/griptape/tokenizers/huggingface_tokenizer.py b/griptape/tokenizers/huggingface_tokenizer.py index dbfba5429..a8312567d 100644 --- a/griptape/tokenizers/huggingface_tokenizer.py +++ b/griptape/tokenizers/huggingface_tokenizer.py @@ -1,6 +1,7 @@ from __future__ import annotations from typing import TYPE_CHECKING from attrs import define, field, Factory +from griptape.utils import import_optional_dependency from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: @@ -9,15 +10,17 @@ @define() class HuggingFaceTokenizer(BaseTokenizer): - tokenizer: PreTrainedTokenizerBase = field(kw_only=True) - model: None = field(init=False, default=None, kw_only=True) + tokenizer: PreTrainedTokenizerBase = field( + default=Factory( + lambda self: import_optional_dependency("transformers").AutoTokenizer.from_pretrained(self.model), + takes_self=True, + ), + kw_only=True, + ) max_input_tokens: int = field( default=Factory(lambda self: self.tokenizer.model_max_length, takes_self=True), kw_only=True ) - max_output_tokens: int = field(kw_only=True) # pyright: ignore[reportGeneralTypeIssues] + max_output_tokens: int = field(default=4096, kw_only=True) - def count_tokens(self, text: str | list) -> int: - if isinstance(text, str): - return len(self.tokenizer.encode(text)) - else: - raise ValueError("Text must be a string.") + def count_tokens(self, text: str) -> int: + return len(self.tokenizer.encode(text)) diff --git a/griptape/tokenizers/openai_tokenizer.py b/griptape/tokenizers/openai_tokenizer.py index ec127ca1a..39a2a033e 100644 --- a/griptape/tokenizers/openai_tokenizer.py +++ b/griptape/tokenizers/openai_tokenizer.py @@ -1,9 +1,9 @@ from __future__ import annotations import logging -from attrs import define +from attrs import define, field, Factory import tiktoken -from griptape.tokenizers import BaseTokenizer from typing import Optional +from griptape.tokenizers import BaseTokenizer @define() @@ -41,6 +41,13 @@ class OpenAiTokenizer(BaseTokenizer): "text-embedding-3-large", ] + max_input_tokens: int = field( + kw_only=True, default=Factory(lambda self: self._default_max_input_tokens(), takes_self=True) + ) + max_output_tokens: int = field( + kw_only=True, default=Factory(lambda self: self._default_max_output_tokens(), takes_self=True) + ) + @property def encoding(self) -> tiktoken.Encoding: try: diff --git a/griptape/tokenizers/simple_tokenizer.py b/griptape/tokenizers/simple_tokenizer.py index 484afe69f..b4e125680 100644 --- a/griptape/tokenizers/simple_tokenizer.py +++ b/griptape/tokenizers/simple_tokenizer.py @@ -1,18 +1,14 @@ from __future__ import annotations -from typing import Optional from attrs import define, field from griptape.tokenizers import BaseTokenizer @define() class SimpleTokenizer(BaseTokenizer): - model: Optional[str] = field(init=False, kw_only=True, default=None) + model: str = field(init=False, kw_only=True) characters_per_token: int = field(kw_only=True) - def count_tokens(self, text: str | list) -> int: - if isinstance(text, str): - num_tokens = (len(text) + self.characters_per_token - 1) // self.characters_per_token + def count_tokens(self, text: str) -> int: + num_tokens = (len(text) + self.characters_per_token - 1) // self.characters_per_token - return num_tokens - else: - raise ValueError("Text must be a string.") + return num_tokens diff --git a/griptape/tokenizers/voyageai_tokenizer.py b/griptape/tokenizers/voyageai_tokenizer.py index 565e53faa..d8fb5adf1 100644 --- a/griptape/tokenizers/voyageai_tokenizer.py +++ b/griptape/tokenizers/voyageai_tokenizer.py @@ -26,8 +26,5 @@ class VoyageAiTokenizer(BaseTokenizer): kw_only=True, ) - def count_tokens(self, text: str | list) -> int: - if isinstance(text, str): - return self.client.count_tokens([text]) - else: - raise ValueError("Text must be a str.") + def count_tokens(self, text: str) -> int: + return self.client.count_tokens([text]) diff --git a/griptape/tools/__init__.py b/griptape/tools/__init__.py index 0c9b6e01d..1c152c95a 100644 --- a/griptape/tools/__init__.py +++ b/griptape/tools/__init__.py @@ -26,6 +26,8 @@ from .griptape_cloud_knowledge_base_client.tool import GriptapeCloudKnowledgeBaseClient from .structure_run_client.tool import StructureRunClient from .image_query_client.tool import ImageQueryClient +from .text_to_speech_client.tool import TextToSpeechClient +from .audio_transcription_client.tool import AudioTranscriptionClient __all__ = [ "BaseTool", @@ -56,4 +58,6 @@ "GriptapeCloudKnowledgeBaseClient", "StructureRunClient", "ImageQueryClient", + "TextToSpeechClient", + "AudioTranscriptionClient", ] diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 917406cdd..6fed6e618 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -48,8 +48,14 @@ def _get_knowledge_base_description(self) -> str: else: url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/") - response = get(url, headers=self.headers).json() - if "description" in response: - return response["description"] + response = get(url, headers=self.headers) + response_body = response.json() + if response.status_code == 200: + if "description" in response_body: + return response_body["description"] + else: + raise ValueError( + f"No description found for Knowledge Base {self.knowledge_base_id}. Please set a description, or manually set the `GriptapeCloudKnowledgeBaseClient.description` attribute." + ) else: - raise ValueError(f'Error getting Knowledge Base description: {response["message"]}') + raise ValueError(f"Error accessing Knowledge Base {self.knowledge_base_id}.") diff --git a/griptape/tools/web_search/tool.py b/griptape/tools/web_search/tool.py index 6ad25ebf0..acc358342 100644 --- a/griptape/tools/web_search/tool.py +++ b/griptape/tools/web_search/tool.py @@ -5,6 +5,7 @@ from griptape.tools import BaseTool from griptape.utils.decorators import activity import requests +import json @define @@ -32,7 +33,7 @@ def search(self, props: dict) -> ListArtifact | ErrorArtifact: query = props["values"]["query"] try: - return ListArtifact([TextArtifact(str(result)) for result in self._search_google(query)]) + return ListArtifact([TextArtifact(json.dumps(result)) for result in self._search_google(query)]) except Exception as e: return ErrorArtifact(f"error searching Google: {e}") diff --git a/griptape/utils/__init__.py b/griptape/utils/__init__.py index 64ca9a9f7..daac63f4e 100644 --- a/griptape/utils/__init__.py +++ b/griptape/utils/__init__.py @@ -14,9 +14,9 @@ from .import_utils import import_optional_dependency from .import_utils import is_dependency_installed from .stream import Stream -from .constants import Constants as constants from .load_artifact_from_memory import load_artifact_from_memory from .deprecation import deprecation_warn +from .structure_visualizer import StructureVisualizer def minify_json(value: str) -> str: @@ -40,9 +40,9 @@ def minify_json(value: str) -> str: "remove_null_values_in_dict_recursively", "dict_merge", "Stream", - "constants", "load_artifact_from_memory", "deprecation_warn", "load_file", "load_files", + "StructureVisualizer", ] diff --git a/griptape/utils/constants.py b/griptape/utils/constants.py index 7bee76750..e69de29bb 100644 --- a/griptape/utils/constants.py +++ b/griptape/utils/constants.py @@ -1,4 +0,0 @@ -class Constants: - # Stop sequence for chain-of-thought in the framework. Using this "token-like" string to make it more unique, - # so that it doesn't trigger on accident. - RESPONSE_STOP_SEQUENCE = "<|Response|>" diff --git a/griptape/utils/prompt_stack.py b/griptape/utils/prompt_stack.py index f04cef486..378f9dd1e 100644 --- a/griptape/utils/prompt_stack.py +++ b/griptape/utils/prompt_stack.py @@ -1,12 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional from attrs import define, field from griptape.mixins import SerializableMixin -if TYPE_CHECKING: - from griptape.memory.structure import BaseConversationMemory - @define class PromptStack(SerializableMixin): @@ -50,50 +46,3 @@ def add_user_input(self, content: str) -> Input: def add_assistant_input(self, content: str) -> Input: return self.add_input(content, self.ASSISTANT_ROLE) - - def add_conversation_memory(self, memory: BaseConversationMemory, index: Optional[int] = None) -> list[Input]: - """Add the Conversation Memory runs to the Prompt Stack. - - If autoprune is enabled, this will fit as many Conversation Memory runs into the Prompt Stack - as possible without exceeding the token limit. - - Args: - memory: The Conversation Memory to add the Prompt Stack to. - index: Optional index to insert the Conversation Memory runs at. - Defaults to appending to the end of the Prompt Stack. - """ - num_runs_to_fit_in_prompt = len(memory.runs) - - if memory.autoprune and hasattr(memory, "structure"): - should_prune = True - prompt_driver = memory.structure.config.prompt_driver - temp_stack = PromptStack() - - # Try to determine how many Conversation Memory runs we can - # fit into the Prompt Stack without exceeding the token limit. - while should_prune and num_runs_to_fit_in_prompt > 0: - temp_stack.inputs = self.inputs.copy() - - # Add n runs from Conversation Memory. - # Where we insert into the Prompt Stack doesn't matter here - # since we only care about the total token count. - memory_inputs = memory.to_prompt_stack(num_runs_to_fit_in_prompt).inputs - temp_stack.inputs.extend(memory_inputs) - - # Convert the prompt stack into tokens left. - prompt_string = prompt_driver.prompt_stack_to_string(temp_stack) - tokens_left = prompt_driver.tokenizer.count_input_tokens_left(prompt_string) - if tokens_left > 0: - # There are still tokens left, no need to prune. - should_prune = False - else: - # There were not any tokens left, prune one run and try again. - num_runs_to_fit_in_prompt -= 1 - - if num_runs_to_fit_in_prompt: - memory_inputs = memory.to_prompt_stack(num_runs_to_fit_in_prompt).inputs - if index: - self.inputs[index:index] = memory_inputs - else: - self.inputs.extend(memory_inputs) - return self.inputs diff --git a/griptape/utils/structure_visualizer.py b/griptape/utils/structure_visualizer.py new file mode 100644 index 000000000..ede282761 --- /dev/null +++ b/griptape/utils/structure_visualizer.py @@ -0,0 +1,42 @@ +from __future__ import annotations +import base64 + +from attrs import define, field +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.tasks import BaseTask + from griptape.structures import Structure + + +@define +class StructureVisualizer: + """Utility class to visualize a Structure structure""" + + structure: Structure = field() + header: str = field(default="graph TD;", kw_only=True) + + def to_url(self) -> str: + """Generates a url that renders the Workflow structure as a Mermaid flowchart + Reference: https://mermaid.js.org/ecosystem/tutorials#jupyter-integration-with-mermaid-js + + Returns: + str: URL to the rendered image + """ + self.structure.resolve_relationships() + + tasks = "\n\t" + "\n\t".join([self.__render_task(task) for task in self.structure.tasks]) + graph = f"{self.header}{tasks}" + + graph_bytes = graph.encode("utf-8") + base64_string = base64.b64encode(graph_bytes).decode("utf-8") + + url = f"https://mermaid.ink/svg/{base64_string}" + + return url + + def __render_task(self, task: BaseTask) -> str: + if task.children: + return f'{task.id}--> {" & ".join([child.id for child in task.children])};' + else: + return f"{task.id};" diff --git a/mkdocs.yml b/mkdocs.yml index 99231cce7..317409c55 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,7 @@ site_name: Griptape Docs hooks: - docs/plugins/swagger_ui_plugin.py +strict: true plugins: - glightbox - search @@ -96,7 +97,6 @@ nav: - Extraction Engines: "griptape-framework/engines/extraction-engines.md" - Summary Engines: "griptape-framework/engines/summary-engines.md" - Image Generation Engines: "griptape-framework/engines/image-generation-engines.md" - - Image Query Engines: "griptape-framework/engines/image-query-engines.md" - Audio Engines: "griptape-framework/engines/audio-engines.md" - Drivers: - Prompt Drivers: "griptape-framework/drivers/prompt-drivers.md" @@ -148,6 +148,7 @@ nav: - ImageQueryClient: "griptape-tools/official-tools/image-query-client.md" - TextToSpeechClient: "griptape-tools/official-tools/text-to-speech-client.md" - AudioTranscriptionClient: "griptape-tools/official-tools/audio-transcription-client.md" + - GriptapeCloudKnowledgeBaseClient: "griptape-tools/official-tools/griptape-cloud-knowledge-base-client.md" - Custom Tools: - Building Custom Tools: "griptape-tools/custom-tools/index.md" - Recipes: diff --git a/poetry.lock b/poetry.lock index cf8fde4ac..b94c05b2a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -278,17 +278,17 @@ lxml = ["lxml"] [[package]] name = "boto3" -version = "1.34.106" +version = "1.34.119" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" files = [ - {file = "boto3-1.34.106-py3-none-any.whl", hash = "sha256:d3be4e1dd5d546a001cd4da805816934cbde9d395316546e9411fec341ade5cf"}, - {file = "boto3-1.34.106.tar.gz", hash = "sha256:6165b8cf1c7e625628ab28b32f9027064c8f5e5fca1c38d7fc228cd22069a19f"}, + {file = "boto3-1.34.119-py3-none-any.whl", hash = "sha256:8f9c43c54b3dfaa36c4a0d7b42c417227a515bc7a2e163e62802780000a5a3e2"}, + {file = "boto3-1.34.119.tar.gz", hash = "sha256:cea2365a25b2b83a97e77f24ac6f922ef62e20636b42f9f6ee9f97188f9c1c03"}, ] [package.dependencies] -botocore = ">=1.34.106,<1.35.0" +botocore = ">=1.34.119,<1.35.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.10.0,<0.11.0" @@ -706,13 +706,13 @@ xray = ["mypy-boto3-xray (>=1.34.0,<1.35.0)"] [[package]] name = "botocore" -version = "1.34.106" +version = "1.34.119" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.106-py3-none-any.whl", hash = "sha256:4baf0e27c2dfc4f4d0dee7c217c716e0782f9b30e8e1fff983fce237d88f73ae"}, - {file = "botocore-1.34.106.tar.gz", hash = "sha256:921fa5202f88c3e58fdcb4b3acffd56d65b24bca47092ee4b27aa988556c0be6"}, + {file = "botocore-1.34.119-py3-none-any.whl", hash = "sha256:4bdf7926a1290b2650d62899ceba65073dd2693e61c35f5cdeb3a286a0aaa27b"}, + {file = "botocore-1.34.119.tar.gz", hash = "sha256:b253f15b24b87b070e176af48e8ef146516090429d30a7d8b136a4c079b28008"}, ] [package.dependencies] @@ -955,13 +955,13 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "cohere" -version = "5.5.0" +version = "5.5.4" description = "" optional = true python-versions = "<4.0,>=3.8" files = [ - {file = "cohere-5.5.0-py3-none-any.whl", hash = "sha256:7792e8898c95f2cb955b2d9f23b8602f73f3b698d59f1a1b4896c53809671da0"}, - {file = "cohere-5.5.0.tar.gz", hash = "sha256:00b492ebf8921e83cb2371f2ee36ddf301422daae3024343a87d4316f02b711b"}, + {file = "cohere-5.5.4-py3-none-any.whl", hash = "sha256:8b692dcb5e86b554e5884168a7d2454951ce102fbd983e9053ec933e06bf02fa"}, + {file = "cohere-5.5.4.tar.gz", hash = "sha256:14acb2ccf272e958f79f9241ae972fd82e96b9b8ee9e6922a5687370761203ec"}, ] [package.dependencies] @@ -971,7 +971,7 @@ httpx = ">=0.21.2" httpx-sse = ">=0.4.0,<0.5.0" pydantic = ">=1.9.2" requests = ">=2.0.0,<3.0.0" -tokenizers = ">=0.19,<0.20" +tokenizers = ">=0.15,<0.16" types-requests = ">=2.0.0,<3.0.0" typing_extensions = ">=4.0.0" @@ -1127,7 +1127,7 @@ test-randomorder = ["pytest-randomly"] name = "dateparser" version = "1.2.0" description = "Date parsing library designed to parse dates from HTML pages" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "dateparser-1.2.0-py2.py3-none-any.whl", hash = "sha256:0b21ad96534e562920a0083e97fd45fa959882d4162acc358705144520a35830"}, @@ -3235,6 +3235,20 @@ files = [ {file = "nvidia_nvtx_cu12-12.1.105-py3-none-win_amd64.whl", hash = "sha256:65f4d98982b31b60026e0e6de73fbdfc09d08a96f4656dd3665ca616a11e1e82"}, ] +[[package]] +name = "ollama" +version = "0.2.1" +description = "The official Python client for Ollama." +optional = true +python-versions = "<4.0,>=3.8" +files = [ + {file = "ollama-0.2.1-py3-none-any.whl", hash = "sha256:b6e2414921c94f573a903d1069d682ba2fb2607070ea9e19ca4a7872f2a460ec"}, + {file = "ollama-0.2.1.tar.gz", hash = "sha256:fa316baa9a81eac3beb4affb0a17deb3008fdd6ed05b123c26306cfbe4c349b6"}, +] + +[package.dependencies] +httpx = ">=0.27.0,<0.28.0" + [[package]] name = "openai" version = "1.30.1" @@ -4248,7 +4262,7 @@ six = ">=1.5" name = "pytz" version = "2024.1" description = "World timezone definitions, modern and historical" -optional = false +optional = true python-versions = "*" files = [ {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, @@ -5263,120 +5277,130 @@ files = [ [[package]] name = "tokenizers" -version = "0.19.1" +version = "0.15.2" description = "" optional = true python-versions = ">=3.7" files = [ - {file = "tokenizers-0.19.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:952078130b3d101e05ecfc7fc3640282d74ed26bcf691400f872563fca15ac97"}, - {file = "tokenizers-0.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82c8b8063de6c0468f08e82c4e198763e7b97aabfe573fd4cf7b33930ca4df77"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:f03727225feaf340ceeb7e00604825addef622d551cbd46b7b775ac834c1e1c4"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:453e4422efdfc9c6b6bf2eae00d5e323f263fff62b29a8c9cd526c5003f3f642"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:02e81bf089ebf0e7f4df34fa0207519f07e66d8491d963618252f2e0729e0b46"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b07c538ba956843833fee1190cf769c60dc62e1cf934ed50d77d5502194d63b1"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28cab1582e0eec38b1f38c1c1fb2e56bce5dc180acb1724574fc5f47da2a4fe"}, - {file = "tokenizers-0.19.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b01afb7193d47439f091cd8f070a1ced347ad0f9144952a30a41836902fe09e"}, - {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:7fb297edec6c6841ab2e4e8f357209519188e4a59b557ea4fafcf4691d1b4c98"}, - {file = "tokenizers-0.19.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2e8a3dd055e515df7054378dc9d6fa8c8c34e1f32777fb9a01fea81496b3f9d3"}, - {file = "tokenizers-0.19.1-cp310-none-win32.whl", hash = "sha256:7ff898780a155ea053f5d934925f3902be2ed1f4d916461e1a93019cc7250837"}, - {file = "tokenizers-0.19.1-cp310-none-win_amd64.whl", hash = "sha256:bea6f9947e9419c2fda21ae6c32871e3d398cba549b93f4a65a2d369662d9403"}, - {file = "tokenizers-0.19.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5c88d1481f1882c2e53e6bb06491e474e420d9ac7bdff172610c4f9ad3898059"}, - {file = "tokenizers-0.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddf672ed719b4ed82b51499100f5417d7d9f6fb05a65e232249268f35de5ed14"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dadc509cc8a9fe460bd274c0e16ac4184d0958117cf026e0ea8b32b438171594"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfedf31824ca4915b511b03441784ff640378191918264268e6923da48104acc"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac11016d0a04aa6487b1513a3a36e7bee7eec0e5d30057c9c0408067345c48d2"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76951121890fea8330d3a0df9a954b3f2a37e3ec20e5b0530e9a0044ca2e11fe"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b342d2ce8fc8d00f376af068e3274e2e8649562e3bc6ae4a67784ded6b99428d"}, - {file = "tokenizers-0.19.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d16ff18907f4909dca9b076b9c2d899114dd6abceeb074eca0c93e2353f943aa"}, - {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:706a37cc5332f85f26efbe2bdc9ef8a9b372b77e4645331a405073e4b3a8c1c6"}, - {file = "tokenizers-0.19.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:16baac68651701364b0289979ecec728546133e8e8fe38f66fe48ad07996b88b"}, - {file = "tokenizers-0.19.1-cp311-none-win32.whl", hash = "sha256:9ed240c56b4403e22b9584ee37d87b8bfa14865134e3e1c3fb4b2c42fafd3256"}, - {file = "tokenizers-0.19.1-cp311-none-win_amd64.whl", hash = "sha256:ad57d59341710b94a7d9dbea13f5c1e7d76fd8d9bcd944a7a6ab0b0da6e0cc66"}, - {file = "tokenizers-0.19.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:621d670e1b1c281a1c9698ed89451395d318802ff88d1fc1accff0867a06f153"}, - {file = "tokenizers-0.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d924204a3dbe50b75630bd16f821ebda6a5f729928df30f582fb5aade90c818a"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:4f3fefdc0446b1a1e6d81cd4c07088ac015665d2e812f6dbba4a06267d1a2c95"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9620b78e0b2d52ef07b0d428323fb34e8ea1219c5eac98c2596311f20f1f9266"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04ce49e82d100594715ac1b2ce87d1a36e61891a91de774755f743babcd0dd52"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5c2ff13d157afe413bf7e25789879dd463e5a4abfb529a2d8f8473d8042e28f"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3174c76efd9d08f836bfccaca7cfec3f4d1c0a4cf3acbc7236ad577cc423c840"}, - {file = "tokenizers-0.19.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c9d5b6c0e7a1e979bec10ff960fae925e947aab95619a6fdb4c1d8ff3708ce3"}, - {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a179856d1caee06577220ebcfa332af046d576fb73454b8f4d4b0ba8324423ea"}, - {file = "tokenizers-0.19.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:952b80dac1a6492170f8c2429bd11fcaa14377e097d12a1dbe0ef2fb2241e16c"}, - {file = "tokenizers-0.19.1-cp312-none-win32.whl", hash = "sha256:01d62812454c188306755c94755465505836fd616f75067abcae529c35edeb57"}, - {file = "tokenizers-0.19.1-cp312-none-win_amd64.whl", hash = "sha256:b70bfbe3a82d3e3fb2a5e9b22a39f8d1740c96c68b6ace0086b39074f08ab89a"}, - {file = "tokenizers-0.19.1-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:bb9dfe7dae85bc6119d705a76dc068c062b8b575abe3595e3c6276480e67e3f1"}, - {file = "tokenizers-0.19.1-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:1f0360cbea28ea99944ac089c00de7b2e3e1c58f479fb8613b6d8d511ce98267"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:71e3ec71f0e78780851fef28c2a9babe20270404c921b756d7c532d280349214"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b82931fa619dbad979c0ee8e54dd5278acc418209cc897e42fac041f5366d626"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e8ff5b90eabdcdaa19af697885f70fe0b714ce16709cf43d4952f1f85299e73a"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e742d76ad84acbdb1a8e4694f915fe59ff6edc381c97d6dfdd054954e3478ad4"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d8c5d59d7b59885eab559d5bc082b2985555a54cda04dda4c65528d90ad252ad"}, - {file = "tokenizers-0.19.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b2da5c32ed869bebd990c9420df49813709e953674c0722ff471a116d97b22d"}, - {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:638e43936cc8b2cbb9f9d8dde0fe5e7e30766a3318d2342999ae27f68fdc9bd6"}, - {file = "tokenizers-0.19.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:78e769eb3b2c79687d9cb0f89ef77223e8e279b75c0a968e637ca7043a84463f"}, - {file = "tokenizers-0.19.1-cp37-none-win32.whl", hash = "sha256:72791f9bb1ca78e3ae525d4782e85272c63faaef9940d92142aa3eb79f3407a3"}, - {file = "tokenizers-0.19.1-cp37-none-win_amd64.whl", hash = "sha256:f3bbb7a0c5fcb692950b041ae11067ac54826204318922da754f908d95619fbc"}, - {file = "tokenizers-0.19.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:07f9295349bbbcedae8cefdbcfa7f686aa420be8aca5d4f7d1ae6016c128c0c5"}, - {file = "tokenizers-0.19.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:10a707cc6c4b6b183ec5dbfc5c34f3064e18cf62b4a938cb41699e33a99e03c1"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6309271f57b397aa0aff0cbbe632ca9d70430839ca3178bf0f06f825924eca22"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ad23d37d68cf00d54af184586d79b84075ada495e7c5c0f601f051b162112dc"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:427c4f0f3df9109314d4f75b8d1f65d9477033e67ffaec4bca53293d3aca286d"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e83a31c9cf181a0a3ef0abad2b5f6b43399faf5da7e696196ddd110d332519ee"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c27b99889bd58b7e301468c0838c5ed75e60c66df0d4db80c08f43462f82e0d3"}, - {file = "tokenizers-0.19.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bac0b0eb952412b0b196ca7a40e7dce4ed6f6926489313414010f2e6b9ec2adf"}, - {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8a6298bde623725ca31c9035a04bf2ef63208d266acd2bed8c2cb7d2b7d53ce6"}, - {file = "tokenizers-0.19.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:08a44864e42fa6d7d76d7be4bec62c9982f6f6248b4aa42f7302aa01e0abfd26"}, - {file = "tokenizers-0.19.1-cp38-none-win32.whl", hash = "sha256:1de5bc8652252d9357a666e609cb1453d4f8e160eb1fb2830ee369dd658e8975"}, - {file = "tokenizers-0.19.1-cp38-none-win_amd64.whl", hash = "sha256:0bcce02bf1ad9882345b34d5bd25ed4949a480cf0e656bbd468f4d8986f7a3f1"}, - {file = "tokenizers-0.19.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:0b9394bd204842a2a1fd37fe29935353742be4a3460b6ccbaefa93f58a8df43d"}, - {file = "tokenizers-0.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4692ab92f91b87769d950ca14dbb61f8a9ef36a62f94bad6c82cc84a51f76f6a"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6258c2ef6f06259f70a682491c78561d492e885adeaf9f64f5389f78aa49a051"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85cf76561fbd01e0d9ea2d1cbe711a65400092bc52b5242b16cfd22e51f0c58"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:670b802d4d82bbbb832ddb0d41df7015b3e549714c0e77f9bed3e74d42400fbe"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:85aa3ab4b03d5e99fdd31660872249df5e855334b6c333e0bc13032ff4469c4a"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbf001afbbed111a79ca47d75941e9e5361297a87d186cbfc11ed45e30b5daba"}, - {file = "tokenizers-0.19.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b4c89aa46c269e4e70c4d4f9d6bc644fcc39bb409cb2a81227923404dd6f5227"}, - {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:39c1ec76ea1027438fafe16ecb0fb84795e62e9d643444c1090179e63808c69d"}, - {file = "tokenizers-0.19.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c2a0d47a89b48d7daa241e004e71fb5a50533718897a4cd6235cb846d511a478"}, - {file = "tokenizers-0.19.1-cp39-none-win32.whl", hash = "sha256:61b7fe8886f2e104d4caf9218b157b106207e0f2a4905c9c7ac98890688aabeb"}, - {file = "tokenizers-0.19.1-cp39-none-win_amd64.whl", hash = "sha256:f97660f6c43efd3e0bfd3f2e3e5615bf215680bad6ee3d469df6454b8c6e8256"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3b11853f17b54c2fe47742c56d8a33bf49ce31caf531e87ac0d7d13d327c9334"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d26194ef6c13302f446d39972aaa36a1dda6450bc8949f5eb4c27f51191375bd"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:e8d1ed93beda54bbd6131a2cb363a576eac746d5c26ba5b7556bc6f964425594"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca407133536f19bdec44b3da117ef0d12e43f6d4b56ac4c765f37eca501c7bda"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce05fde79d2bc2e46ac08aacbc142bead21614d937aac950be88dc79f9db9022"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:35583cd46d16f07c054efd18b5d46af4a2f070a2dd0a47914e66f3ff5efb2b1e"}, - {file = "tokenizers-0.19.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:43350270bfc16b06ad3f6f07eab21f089adb835544417afda0f83256a8bf8b75"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b4399b59d1af5645bcee2072a463318114c39b8547437a7c2d6a186a1b5a0e2d"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6852c5b2a853b8b0ddc5993cd4f33bfffdca4fcc5d52f89dd4b8eada99379285"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bcd266ae85c3d39df2f7e7d0e07f6c41a55e9a3123bb11f854412952deacd828"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ecb2651956eea2aa0a2d099434134b1b68f1c31f9a5084d6d53f08ed43d45ff2"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b279ab506ec4445166ac476fb4d3cc383accde1ea152998509a94d82547c8e2a"}, - {file = "tokenizers-0.19.1-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:89183e55fb86e61d848ff83753f64cded119f5d6e1f553d14ffee3700d0a4a49"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2edbc75744235eea94d595a8b70fe279dd42f3296f76d5a86dde1d46e35f574"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:0e64bfde9a723274e9a71630c3e9494ed7b4c0f76a1faacf7fe294cd26f7ae7c"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0b5ca92bfa717759c052e345770792d02d1f43b06f9e790ca0a1db62838816f3"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f8a20266e695ec9d7a946a019c1d5ca4eddb6613d4f466888eee04f16eedb85"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63c38f45d8f2a2ec0f3a20073cccb335b9f99f73b3c69483cd52ebc75369d8a1"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dd26e3afe8a7b61422df3176e06664503d3f5973b94f45d5c45987e1cb711876"}, - {file = "tokenizers-0.19.1-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:eddd5783a4a6309ce23432353cdb36220e25cbb779bfa9122320666508b44b88"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:56ae39d4036b753994476a1b935584071093b55c7a72e3b8288e68c313ca26e7"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:f9939ca7e58c2758c01b40324a59c034ce0cebad18e0d4563a9b1beab3018243"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6c330c0eb815d212893c67a032e9dc1b38a803eccb32f3e8172c19cc69fbb439"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec11802450a2487cdf0e634b750a04cbdc1c4d066b97d94ce7dd2cb51ebb325b"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a2b718f316b596f36e1dae097a7d5b91fc5b85e90bf08b01ff139bd8953b25af"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:ed69af290c2b65169f0ba9034d1dc39a5db9459b32f1dd8b5f3f32a3fcf06eab"}, - {file = "tokenizers-0.19.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f8a9c828277133af13f3859d1b6bf1c3cb6e9e1637df0e45312e6b7c2e622b1f"}, - {file = "tokenizers-0.19.1.tar.gz", hash = "sha256:ee59e6680ed0fdbe6b724cf38bd70400a0c1dd623b07ac729087270caeac88e3"}, -] - -[package.dependencies] -huggingface-hub = ">=0.16.4,<1.0" + {file = "tokenizers-0.15.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:52f6130c9cbf70544287575a985bf44ae1bda2da7e8c24e97716080593638012"}, + {file = "tokenizers-0.15.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:054c1cc9c6d68f7ffa4e810b3d5131e0ba511b6e4be34157aa08ee54c2f8d9ee"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a9b9b070fdad06e347563b88c278995735292ded1132f8657084989a4c84a6d5"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea621a7eef4b70e1f7a4e84dd989ae3f0eeb50fc8690254eacc08acb623e82f1"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf7fd9a5141634fa3aa8d6b7be362e6ae1b4cda60da81388fa533e0b552c98fd"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44f2a832cd0825295f7179eaf173381dc45230f9227ec4b44378322d900447c9"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8b9ec69247a23747669ec4b0ca10f8e3dfb3545d550258129bd62291aabe8605"}, + {file = "tokenizers-0.15.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40b6a4c78da863ff26dbd5ad9a8ecc33d8a8d97b535172601cf00aee9d7ce9ce"}, + {file = "tokenizers-0.15.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:5ab2a4d21dcf76af60e05af8063138849eb1d6553a0d059f6534357bce8ba364"}, + {file = "tokenizers-0.15.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a47acfac7e511f6bbfcf2d3fb8c26979c780a91e06fb5b9a43831b2c0153d024"}, + {file = "tokenizers-0.15.2-cp310-none-win32.whl", hash = "sha256:064ff87bb6acdbd693666de9a4b692add41308a2c0ec0770d6385737117215f2"}, + {file = "tokenizers-0.15.2-cp310-none-win_amd64.whl", hash = "sha256:3b919afe4df7eb6ac7cafd2bd14fb507d3f408db7a68c43117f579c984a73843"}, + {file = "tokenizers-0.15.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:89cd1cb93e4b12ff39bb2d626ad77e35209de9309a71e4d3d4672667b4b256e7"}, + {file = "tokenizers-0.15.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cfed5c64e5be23d7ee0f0e98081a25c2a46b0b77ce99a4f0605b1ec43dd481fa"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a907d76dcfda37023ba203ab4ceeb21bc5683436ebefbd895a0841fd52f6f6f2"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20ea60479de6fc7b8ae756b4b097572372d7e4032e2521c1bbf3d90c90a99ff0"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:48e2b9335be2bc0171df9281385c2ed06a15f5cf121c44094338306ab7b33f2c"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:112a1dd436d2cc06e6ffdc0b06d55ac019a35a63afd26475205cb4b1bf0bfbff"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4620cca5c2817177ee8706f860364cc3a8845bc1e291aaf661fb899e5d1c45b0"}, + {file = "tokenizers-0.15.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ccd73a82751c523b3fc31ff8194702e4af4db21dc20e55b30ecc2079c5d43cb7"}, + {file = "tokenizers-0.15.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:107089f135b4ae7817affe6264f8c7a5c5b4fd9a90f9439ed495f54fcea56fb4"}, + {file = "tokenizers-0.15.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0ff110ecc57b7aa4a594396525a3451ad70988e517237fe91c540997c4e50e29"}, + {file = "tokenizers-0.15.2-cp311-none-win32.whl", hash = "sha256:6d76f00f5c32da36c61f41c58346a4fa7f0a61be02f4301fd30ad59834977cc3"}, + {file = "tokenizers-0.15.2-cp311-none-win_amd64.whl", hash = "sha256:cc90102ed17271cf0a1262babe5939e0134b3890345d11a19c3145184b706055"}, + {file = "tokenizers-0.15.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f86593c18d2e6248e72fb91c77d413a815153b8ea4e31f7cd443bdf28e467670"}, + {file = "tokenizers-0.15.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0774bccc6608eca23eb9d620196687c8b2360624619623cf4ba9dc9bd53e8b51"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d0222c5b7c9b26c0b4822a82f6a7011de0a9d3060e1da176f66274b70f846b98"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3835738be1de66624fff2f4f6f6684775da4e9c00bde053be7564cbf3545cc66"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0143e7d9dcd811855c1ce1ab9bf5d96d29bf5e528fd6c7824d0465741e8c10fd"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db35825f6d54215f6b6009a7ff3eedee0848c99a6271c870d2826fbbedf31a38"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f5e64b0389a2be47091d8cc53c87859783b837ea1a06edd9d8e04004df55a5c"}, + {file = "tokenizers-0.15.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e0480c452217edd35eca56fafe2029fb4d368b7c0475f8dfa3c5c9c400a7456"}, + {file = "tokenizers-0.15.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a33ab881c8fe70474980577e033d0bc9a27b7ab8272896e500708b212995d834"}, + {file = "tokenizers-0.15.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a308a607ca9de2c64c1b9ba79ec9a403969715a1b8ba5f998a676826f1a7039d"}, + {file = "tokenizers-0.15.2-cp312-none-win32.whl", hash = "sha256:b8fcfa81bcb9447df582c5bc96a031e6df4da2a774b8080d4f02c0c16b42be0b"}, + {file = "tokenizers-0.15.2-cp312-none-win_amd64.whl", hash = "sha256:38d7ab43c6825abfc0b661d95f39c7f8af2449364f01d331f3b51c94dcff7221"}, + {file = "tokenizers-0.15.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:38bfb0204ff3246ca4d5e726e8cc8403bfc931090151e6eede54d0e0cf162ef0"}, + {file = "tokenizers-0.15.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c861d35e8286a53e06e9e28d030b5a05bcbf5ac9d7229e561e53c352a85b1fc"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:936bf3842db5b2048eaa53dade907b1160f318e7c90c74bfab86f1e47720bdd6"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:620beacc3373277700d0e27718aa8b25f7b383eb8001fba94ee00aeea1459d89"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2735ecbbf37e52db4ea970e539fd2d450d213517b77745114f92867f3fc246eb"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:473c83c5e2359bb81b0b6fde870b41b2764fcdd36d997485e07e72cc3a62264a"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:968fa1fb3c27398b28a4eca1cbd1e19355c4d3a6007f7398d48826bbe3a0f728"}, + {file = "tokenizers-0.15.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:865c60ae6eaebdde7da66191ee9b7db52e542ed8ee9d2c653b6d190a9351b980"}, + {file = "tokenizers-0.15.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7c0d8b52664ab2d4a8d6686eb5effc68b78608a9008f086a122a7b2996befbab"}, + {file = "tokenizers-0.15.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:f33dfbdec3784093a9aebb3680d1f91336c56d86cc70ddf88708251da1fe9064"}, + {file = "tokenizers-0.15.2-cp37-cp37m-macosx_10_12_x86_64.whl", hash = "sha256:d44ba80988ff9424e33e0a49445072ac7029d8c0e1601ad25a0ca5f41ed0c1d6"}, + {file = "tokenizers-0.15.2-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:dce74266919b892f82b1b86025a613956ea0ea62a4843d4c4237be2c5498ed3a"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0ef06b9707baeb98b316577acb04f4852239d856b93e9ec3a299622f6084e4be"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c73e2e74bbb07910da0d37c326869f34113137b23eadad3fc00856e6b3d9930c"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4eeb12daf02a59e29f578a865f55d87cd103ce62bd8a3a5874f8fdeaa82e336b"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ba9f6895af58487ca4f54e8a664a322f16c26bbb442effd01087eba391a719e"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccec77aa7150e38eec6878a493bf8c263ff1fa8a62404e16c6203c64c1f16a26"}, + {file = "tokenizers-0.15.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3f40604f5042ff210ba82743dda2b6aa3e55aa12df4e9f2378ee01a17e2855e"}, + {file = "tokenizers-0.15.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5645938a42d78c4885086767c70923abad047163d809c16da75d6b290cb30bbe"}, + {file = "tokenizers-0.15.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:05a77cbfebe28a61ab5c3891f9939cc24798b63fa236d84e5f29f3a85a200c00"}, + {file = "tokenizers-0.15.2-cp37-none-win32.whl", hash = "sha256:361abdc068e8afe9c5b818769a48624687fb6aaed49636ee39bec4e95e1a215b"}, + {file = "tokenizers-0.15.2-cp37-none-win_amd64.whl", hash = "sha256:7ef789f83eb0f9baeb4d09a86cd639c0a5518528f9992f38b28e819df397eb06"}, + {file = "tokenizers-0.15.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4fe1f74a902bee74a3b25aff180fbfbf4f8b444ab37c4d496af7afd13a784ed2"}, + {file = "tokenizers-0.15.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c4b89038a684f40a6b15d6b09f49650ac64d951ad0f2a3ea9169687bbf2a8ba"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:d05a1b06f986d41aed5f2de464c003004b2df8aaf66f2b7628254bcbfb72a438"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:508711a108684111ec8af89d3a9e9e08755247eda27d0ba5e3c50e9da1600f6d"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:daa348f02d15160cb35439098ac96e3a53bacf35885072611cd9e5be7d333daa"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:494fdbe5932d3416de2a85fc2470b797e6f3226c12845cadf054dd906afd0442"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2d60f5246f4da9373f75ff18d64c69cbf60c3bca597290cea01059c336d2470"}, + {file = "tokenizers-0.15.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93268e788825f52de4c7bdcb6ebc1fcd4a5442c02e730faa9b6b08f23ead0e24"}, + {file = "tokenizers-0.15.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6fc7083ab404019fc9acafe78662c192673c1e696bd598d16dc005bd663a5cf9"}, + {file = "tokenizers-0.15.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:41e39b41e5531d6b2122a77532dbea60e171ef87a3820b5a3888daa847df4153"}, + {file = "tokenizers-0.15.2-cp38-none-win32.whl", hash = "sha256:06cd0487b1cbfabefb2cc52fbd6b1f8d4c37799bd6c6e1641281adaa6b2504a7"}, + {file = "tokenizers-0.15.2-cp38-none-win_amd64.whl", hash = "sha256:5179c271aa5de9c71712e31cb5a79e436ecd0d7532a408fa42a8dbfa4bc23fd9"}, + {file = "tokenizers-0.15.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:82f8652a74cc107052328b87ea8b34291c0f55b96d8fb261b3880216a9f9e48e"}, + {file = "tokenizers-0.15.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:02458bee6f5f3139f1ebbb6d042b283af712c0981f5bc50edf771d6b762d5e4f"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:c9a09cd26cca2e1c349f91aa665309ddb48d71636370749414fbf67bc83c5343"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:158be8ea8554e5ed69acc1ce3fbb23a06060bd4bbb09029431ad6b9a466a7121"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ddba9a2b0c8c81633eca0bb2e1aa5b3a15362b1277f1ae64176d0f6eba78ab1"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ef5dd1d39797044642dbe53eb2bc56435308432e9c7907728da74c69ee2adca"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:454c203164e07a860dbeb3b1f4a733be52b0edbb4dd2e5bd75023ffa8b49403a"}, + {file = "tokenizers-0.15.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cf6b7f1d4dc59af960e6ffdc4faffe6460bbfa8dce27a58bf75755ffdb2526d"}, + {file = "tokenizers-0.15.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2ef09bbc16519f6c25d0c7fc0c6a33a6f62923e263c9d7cca4e58b8c61572afb"}, + {file = "tokenizers-0.15.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c9a2ebdd2ad4ec7a68e7615086e633857c85e2f18025bd05d2a4399e6c5f7169"}, + {file = "tokenizers-0.15.2-cp39-none-win32.whl", hash = "sha256:918fbb0eab96fe08e72a8c2b5461e9cce95585d82a58688e7f01c2bd546c79d0"}, + {file = "tokenizers-0.15.2-cp39-none-win_amd64.whl", hash = "sha256:524e60da0135e106b254bd71f0659be9f89d83f006ea9093ce4d1fab498c6d0d"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6a9b648a58281c4672212fab04e60648fde574877d0139cd4b4f93fe28ca8944"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7c7d18b733be6bbca8a55084027f7be428c947ddf871c500ee603e375013ffba"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:13ca3611de8d9ddfbc4dc39ef54ab1d2d4aaa114ac8727dfdc6a6ec4be017378"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:237d1bf3361cf2e6463e6c140628e6406766e8b27274f5fcc62c747ae3c6f094"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67a0fe1e49e60c664915e9fb6b0cb19bac082ab1f309188230e4b2920230edb3"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4e022fe65e99230b8fd89ebdfea138c24421f91c1a4f4781a8f5016fd5cdfb4d"}, + {file = "tokenizers-0.15.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d857be2df69763362ac699f8b251a8cd3fac9d21893de129bc788f8baaef2693"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-macosx_10_12_x86_64.whl", hash = "sha256:708bb3e4283177236309e698da5fcd0879ce8fd37457d7c266d16b550bcbbd18"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:64c35e09e9899b72a76e762f9854e8750213f67567787d45f37ce06daf57ca78"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1257f4394be0d3b00de8c9e840ca5601d0a4a8438361ce9c2b05c7d25f6057b"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02272fe48280e0293a04245ca5d919b2c94a48b408b55e858feae9618138aeda"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:dc3ad9ebc76eabe8b1d7c04d38be884b8f9d60c0cdc09b0aa4e3bcf746de0388"}, + {file = "tokenizers-0.15.2-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:32e16bdeffa7c4f46bf2152172ca511808b952701d13e7c18833c0b73cb5c23f"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:fb16ba563d59003028b678d2361a27f7e4ae0ab29c7a80690efa20d829c81fdb"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:2277c36d2d6cdb7876c274547921a42425b6810d38354327dd65a8009acf870c"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1cf75d32e8d250781940d07f7eece253f2fe9ecdb1dc7ba6e3833fa17b82fcbc"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1b3b31884dc8e9b21508bb76da80ebf7308fdb947a17affce815665d5c4d028"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b10122d8d8e30afb43bb1fe21a3619f62c3e2574bff2699cf8af8b0b6c5dc4a3"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d88b96ff0fe8e91f6ef01ba50b0d71db5017fa4e3b1d99681cec89a85faf7bf7"}, + {file = "tokenizers-0.15.2-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:37aaec5a52e959892870a7c47cef80c53797c0db9149d458460f4f31e2fb250e"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e2ea752f2b0fe96eb6e2f3adbbf4d72aaa1272079b0dfa1145507bd6a5d537e6"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:4b19a808d8799fda23504a5cd31d2f58e6f52f140380082b352f877017d6342b"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:64c86e5e068ac8b19204419ed8ca90f9d25db20578f5881e337d203b314f4104"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:de19c4dc503c612847edf833c82e9f73cd79926a384af9d801dcf93f110cea4e"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ea09acd2fe3324174063d61ad620dec3bcf042b495515f27f638270a7d466e8b"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cf27fd43472e07b57cf420eee1e814549203d56de00b5af8659cb99885472f1f"}, + {file = "tokenizers-0.15.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7ca22bd897537a0080521445d91a58886c8c04084a6a19e6c78c586e0cfa92a5"}, + {file = "tokenizers-0.15.2.tar.gz", hash = "sha256:e6e9c6e019dd5484be5beafc775ae6c925f4c69a3487040ed09b45e13df2cb91"}, +] + +[package.dependencies] +huggingface_hub = ">=0.16.4,<1.0" [package.extras] dev = ["tokenizers[testing]"] -docs = ["setuptools-rust", "sphinx", "sphinx-rtd-theme"] -testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests", "ruff"] +docs = ["setuptools_rust", "sphinx", "sphinx_rtd_theme"] +testing = ["black (==22.3)", "datasets", "numpy", "pytest", "requests"] [[package]] name = "tomli" @@ -5515,13 +5539,13 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "transformers" -version = "4.40.2" +version = "4.39.3" description = "State-of-the-art Machine Learning for JAX, PyTorch and TensorFlow" optional = true python-versions = ">=3.8.0" files = [ - {file = "transformers-4.40.2-py3-none-any.whl", hash = "sha256:71cb94301ec211a2e1d4b8c8d18dcfaa902dfa00a089dceca167a8aa265d6f2d"}, - {file = "transformers-4.40.2.tar.gz", hash = "sha256:657b6054a2097671398d976ad46e60836e7e15f9ea9551631a96e33cb9240649"}, + {file = "transformers-4.39.3-py3-none-any.whl", hash = "sha256:7838034a12cca3168247f9d2d1dba6724c9de3ae0f73a108258c6b8fc5912601"}, + {file = "transformers-4.39.3.tar.gz", hash = "sha256:2586e5ff4150f122716fc40f5530e92871befc051848fbe82600969c535b762d"}, ] [package.dependencies] @@ -5533,21 +5557,21 @@ pyyaml = ">=5.1" regex = "!=2019.12.17" requests = "*" safetensors = ">=0.4.1" -tokenizers = ">=0.19,<0.20" +tokenizers = ">=0.14,<0.19" tqdm = ">=4.27" [package.extras] accelerate = ["accelerate (>=0.21.0)"] agents = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "datasets (!=2.5.0)", "diffusers", "opencv-python", "sentencepiece (>=0.1.91,!=0.1.92)", "torch"] -all = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune] (>=2.7.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timm", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision"] +all = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune] (>=2.7.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timm", "tokenizers (>=0.14,<0.19)", "torch", "torchaudio", "torchvision"] audio = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] codecarbon = ["codecarbon (==1.2.0)"] deepspeed = ["accelerate (>=0.21.0)", "deepspeed (>=0.9.3)"] deepspeed-testing = ["GitPython (<3.1.19)", "accelerate (>=0.21.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "deepspeed (>=0.9.3)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder (>=0.3.0)", "nltk", "optuna", "parameterized", "protobuf", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] -dev = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "decord (==0.6.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "flax (>=0.4.1,<=0.7.0)", "fugashi (>=1.0)", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "timm", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] -dev-tensorflow = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "isort (>=5.5.4)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "tokenizers (>=0.19,<0.20)", "urllib3 (<2.0.0)"] -dev-torch = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "fugashi (>=1.0)", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "kenlm", "librosa", "nltk", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "timeout-decorator", "timm", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] -docs = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "hf-doc-builder", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune] (>=2.7.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timm", "tokenizers (>=0.19,<0.20)", "torch", "torchaudio", "torchvision"] +dev = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "decord (==0.6.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "flax (>=0.4.1,<=0.7.0)", "fugashi (>=1.0)", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "timm", "tokenizers (>=0.14,<0.19)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] +dev-tensorflow = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "isort (>=5.5.4)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "nltk", "onnxconverter-common", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timeout-decorator", "tokenizers (>=0.14,<0.19)", "urllib3 (<2.0.0)"] +dev-torch = ["GitPython (<3.1.19)", "Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "beautifulsoup4", "codecarbon (==1.2.0)", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "fugashi (>=1.0)", "hf-doc-builder", "hf-doc-builder (>=0.3.0)", "ipadic (>=1.0.0,<2.0)", "isort (>=5.5.4)", "kenlm", "librosa", "nltk", "onnxruntime (>=1.4.0)", "onnxruntime-tools (>=1.4.2)", "optuna", "parameterized", "phonemizer", "protobuf", "psutil", "pyctcdecode (>=0.4.0)", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "ray[tune] (>=2.7.0)", "rhoknp (>=1.1.0,<1.3.1)", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "scikit-learn", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "sudachidict-core (>=20220729)", "sudachipy (>=0.6.6)", "tensorboard", "timeout-decorator", "timm", "tokenizers (>=0.14,<0.19)", "torch", "torchaudio", "torchvision", "unidic (>=1.0.2)", "unidic-lite (>=1.0.7)", "urllib3 (<2.0.0)"] +docs = ["Pillow (>=10.0.1,<=15.0)", "accelerate (>=0.21.0)", "av (==9.2.0)", "codecarbon (==1.2.0)", "decord (==0.6.0)", "flax (>=0.4.1,<=0.7.0)", "hf-doc-builder", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "kenlm", "keras-nlp (>=0.3.1)", "librosa", "onnxconverter-common", "optax (>=0.0.8,<=0.1.4)", "optuna", "phonemizer", "protobuf", "pyctcdecode (>=0.4.0)", "ray[tune] (>=2.7.0)", "sentencepiece (>=0.1.91,!=0.1.92)", "sigopt", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx", "timm", "tokenizers (>=0.14,<0.19)", "torch", "torchaudio", "torchvision"] docs-specific = ["hf-doc-builder"] flax = ["flax (>=0.4.1,<=0.7.0)", "jax (>=0.4.1,<=0.4.13)", "jaxlib (>=0.4.1,<=0.4.13)", "optax (>=0.0.8,<=0.1.4)"] flax-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] @@ -5568,16 +5592,16 @@ serving = ["fastapi", "pydantic", "starlette", "uvicorn"] sigopt = ["sigopt"] sklearn = ["scikit-learn"] speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"] -testing = ["GitPython (<3.1.19)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder (>=0.3.0)", "nltk", "parameterized", "protobuf", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "sentencepiece (>=0.1.91,!=0.1.92)", "tensorboard", "timeout-decorator"] +testing = ["GitPython (<3.1.19)", "beautifulsoup4", "cookiecutter (==1.7.3)", "datasets (!=2.5.0)", "dill (<0.3.5)", "evaluate (>=0.2.0)", "faiss-cpu", "hf-doc-builder (>=0.3.0)", "nltk", "parameterized", "protobuf", "psutil", "pydantic", "pytest (>=7.2.0,<8.0.0)", "pytest-timeout", "pytest-xdist", "rjieba", "rouge-score (!=0.0.7,!=0.0.8,!=0.1,!=0.1.1)", "ruff (==0.1.5)", "sacrebleu (>=1.4.12,<2.0.0)", "sacremoses", "tensorboard", "timeout-decorator"] tf = ["keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx"] tf-cpu = ["keras-nlp (>=0.3.1)", "onnxconverter-common", "tensorflow-cpu (>=2.6,<2.16)", "tensorflow-text (<2.16)", "tf2onnx"] tf-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)"] timm = ["timm"] -tokenizers = ["tokenizers (>=0.19,<0.20)"] +tokenizers = ["tokenizers (>=0.14,<0.19)"] torch = ["accelerate (>=0.21.0)", "torch"] torch-speech = ["kenlm", "librosa", "phonemizer", "pyctcdecode (>=0.4.0)", "torchaudio"] torch-vision = ["Pillow (>=10.0.1,<=15.0)", "torchvision"] -torchhub = ["filelock", "huggingface-hub (>=0.19.3,<1.0)", "importlib-metadata", "numpy (>=1.17)", "packaging (>=20.0)", "protobuf", "regex (!=2019.12.17)", "requests", "sentencepiece (>=0.1.91,!=0.1.92)", "tokenizers (>=0.19,<0.20)", "torch", "tqdm (>=4.27)"] +torchhub = ["filelock", "huggingface-hub (>=0.19.3,<1.0)", "importlib-metadata", "numpy (>=1.17)", "packaging (>=20.0)", "protobuf", "regex (!=2019.12.17)", "requests", "sentencepiece (>=0.1.91,!=0.1.92)", "tokenizers (>=0.14,<0.19)", "torch", "tqdm (>=4.27)"] video = ["av (==9.2.0)", "decord (==0.6.0)"] vision = ["Pillow (>=10.0.1,<=15.0)"] @@ -5688,7 +5712,7 @@ files = [ name = "tzdata" version = "2024.1" description = "Provider of IANA time zone data" -optional = false +optional = true python-versions = ">=2" files = [ {file = "tzdata-2024.1-py2.py3-none-any.whl", hash = "sha256:9068bc196136463f5245e51efda838afa15aaeca9903f49050dfa2679db4d252"}, @@ -5699,7 +5723,7 @@ files = [ name = "tzlocal" version = "5.2" description = "tzinfo object for the local timezone" -optional = false +optional = true python-versions = ">=3.8" files = [ {file = "tzlocal-5.2-py3-none-any.whl", hash = "sha256:49816ef2fe65ea8ac19d19aa7a1ae0551c834303d5014c6d5a62e4cbda8047b8"}, @@ -6046,9 +6070,10 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] +drivers-embedding-cohere = ["cohere"] drivers-embedding-google = ["google-generativeai"] drivers-embedding-huggingface = ["huggingface-hub", "transformers"] drivers-embedding-voyageai = ["voyageai"] @@ -6064,6 +6089,7 @@ drivers-prompt-cohere = ["cohere"] drivers-prompt-google = ["google-generativeai"] drivers-prompt-huggingface = ["huggingface-hub", "transformers"] drivers-prompt-huggingface-pipeline = ["huggingface-hub", "torch", "transformers"] +drivers-prompt-ollama = ["ollama"] drivers-sql-postgres = ["pgvector", "psycopg2-binary"] drivers-sql-redshift = ["boto3", "sqlalchemy-redshift"] drivers-sql-snowflake = ["snowflake-sqlalchemy"] @@ -6085,4 +6111,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "4e98cb17a098a86dc3c109bad3cb8b5299e333d20e7c12903a7fe9472b7a3d31" +content-hash = "6ccbbba60b534e4756d1c36e37ce1379ee2126d37b822f186b5dbb8e8f701ff3" diff --git a/pyproject.toml b/pyproject.toml index 60fc345f2..0869256a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "griptape" -version = "0.26.0" +version = "0.27.0" description = "Modular Python framework for LLM workflows, tools, memory, and data." authors = ["Griptape "] license = "Apache 2.0" @@ -27,15 +27,14 @@ numpy = ">=1" stringcase = "^1.2.0" docker = "^7.1.0" sqlalchemy = "~=1.0" -dateparser = "^1.1.8" requests = "^2" # drivers -cohere = { version = ">=4", optional = true } +cohere = { version = "^5.5.4", optional = true } anthropic = { version = "^0.20.0", optional = true } -transformers = { version = "^4.30", optional = true } +transformers = { version = "^4.39.3", optional = true } huggingface-hub = { version = ">=0.13", optional = true } -boto3 = { version = "^1.28.2", optional = true } +boto3 = { version = "^1.34.119", optional = true } sqlalchemy-redshift = { version = "*", optional = true } snowflake-sqlalchemy = { version = "^1.4.7", optional = true } pinecone-client = { version = "^3", optional = true } @@ -54,6 +53,7 @@ voyageai = {version = "^0.2.1", optional = true} elevenlabs = {version = "^1.1.2", optional = true} torch = {version = "^2.3.0", optional = true} pusher = {version = "^3.3.2", optional = true} +ollama = {version = "^0.2.1", optional = true} # loaders pandas = {version = "^1.3", optional = true} @@ -70,6 +70,7 @@ drivers-prompt-huggingface-pipeline = ["huggingface-hub", "transformers", "torch drivers-prompt-amazon-bedrock = ["boto3", "anthropic"] drivers-prompt-amazon-sagemaker = ["boto3", "transformers"] drivers-prompt-google = ["google-generativeai"] +drivers-prompt-ollama = ["ollama"] drivers-sql-redshift = ["sqlalchemy-redshift", "boto3"] drivers-sql-snowflake = ["snowflake-sqlalchemy", "snowflake", "snowflake-connector-python"] @@ -91,6 +92,7 @@ drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-huggingface = ["huggingface-hub", "transformers"] drivers-embedding-voyageai = ["voyageai"] drivers-embedding-google = ["google-generativeai"] +drivers-embedding-cohere = ["cohere"] drivers-web-scraper-trafilatura = ["trafilatura"] drivers-web-scraper-markdownify = ["playwright", "beautifulsoup4", "markdownify"] @@ -131,6 +133,7 @@ all = [ "elevenlabs", "torch", "pusher", + "ollama", # loaders "pandas", diff --git a/tests/mocks/mock_audio_input_task.py b/tests/mocks/mock_audio_input_task.py new file mode 100644 index 000000000..d6a27d968 --- /dev/null +++ b/tests/mocks/mock_audio_input_task.py @@ -0,0 +1,9 @@ +from attrs import define +from griptape.artifacts import TextArtifact +from griptape.tasks.base_audio_input_task import BaseAudioInputTask + + +@define +class MockAudioInputTask(BaseAudioInputTask): + def run(self) -> TextArtifact: + return TextArtifact(self.input.to_text()) diff --git a/tests/mocks/mock_prompt_driver.py b/tests/mocks/mock_prompt_driver.py index dc4cde69e..3235f7cd5 100644 --- a/tests/mocks/mock_prompt_driver.py +++ b/tests/mocks/mock_prompt_driver.py @@ -13,10 +13,15 @@ class MockPromptDriver(BasePromptDriver): model: str = "test-model" tokenizer: BaseTokenizer = MockTokenizer(model="test-model", max_input_tokens=4096, max_output_tokens=4096) - mock_output: str | Callable[[], str] = field(default="mock output", kw_only=True) + mock_input: str | Callable[[], str] = field(default="mock input", kw_only=True) + mock_output: str | Callable[[PromptStack], str] = field(default="mock output", kw_only=True) def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - return TextArtifact(value=self.mock_output() if isinstance(self.mock_output, Callable) else self.mock_output) + return TextArtifact( + value=self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output + ) def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - yield TextArtifact(value=self.mock_output() if isinstance(self.mock_output, Callable) else self.mock_output) + yield TextArtifact( + value=self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output + ) diff --git a/tests/mocks/mock_tokenizer.py b/tests/mocks/mock_tokenizer.py index a333f9a13..eff103e99 100644 --- a/tests/mocks/mock_tokenizer.py +++ b/tests/mocks/mock_tokenizer.py @@ -1,13 +1,9 @@ from __future__ import annotations -from attrs import define, field +from attrs import define from griptape.tokenizers import BaseTokenizer @define() class MockTokenizer(BaseTokenizer): - model: str = field(kw_only=True) - max_input_tokens: int = field(default=1000, kw_only=True) - max_output_tokens: int = field(default=1000, kw_only=True) - - def count_tokens(self, text: str | list[dict]) -> int: + def count_tokens(self, text: str) -> int: return len(text) diff --git a/tests/unit/chunkers/test_text_chunker.py b/tests/unit/chunkers/test_text_chunker.py index c1fb40137..243b287e1 100644 --- a/tests/unit/chunkers/test_text_chunker.py +++ b/tests/unit/chunkers/test_text_chunker.py @@ -106,3 +106,7 @@ def test_separators(self, chunker): assert chunks[5].value.endswith("? foo-12?") assert chunks[6].value.endswith(" foo-5") assert chunks[7].value.endswith(" foo-16") + + def test_chunk_with_max_tokens(self, chunker): + with pytest.raises(ValueError): + TextChunker(max_tokens=-1) diff --git a/tests/unit/config/test_amazon_bedrock_structure_config.py b/tests/unit/config/test_amazon_bedrock_structure_config.py index 5b8c63a98..33b286f94 100644 --- a/tests/unit/config/test_amazon_bedrock_structure_config.py +++ b/tests/unit/config/test_amazon_bedrock_structure_config.py @@ -38,7 +38,6 @@ def test_to_dict(self, config): "prompt_driver": { "max_tokens": None, "model": "anthropic.claude-3-sonnet-20240229-v1:0", - "prompt_model_driver": {"type": "BedrockClaudePromptModelDriver", "top_k": 250, "top_p": 0.999}, "stream": False, "temperature": 0.1, "type": "AmazonBedrockPromptDriver", diff --git a/tests/unit/config/test_anthropic_structure_config.py b/tests/unit/config/test_anthropic_structure_config.py index 8279fb091..1dd83f96c 100644 --- a/tests/unit/config/test_anthropic_structure_config.py +++ b/tests/unit/config/test_anthropic_structure_config.py @@ -18,7 +18,7 @@ def test_to_dict(self, config): "prompt_driver": { "type": "AnthropicPromptDriver", "temperature": 0.1, - "max_tokens": None, + "max_tokens": 1000, "stream": False, "model": "claude-3-opus-20240229", "top_p": 0.999, diff --git a/tests/unit/config/test_cohere_structure_config.py b/tests/unit/config/test_cohere_structure_config.py new file mode 100644 index 000000000..1dc585421 --- /dev/null +++ b/tests/unit/config/test_cohere_structure_config.py @@ -0,0 +1,38 @@ +from pytest import fixture +from griptape.config import CohereStructureConfig + + +class TestCohereStructureConfig: + @fixture + def config(self): + return CohereStructureConfig(api_key="api_key") + + def test_to_dict(self, config): + assert config.to_dict() == { + "type": "CohereStructureConfig", + "image_generation_driver": {"type": "DummyImageGenerationDriver"}, + "image_query_driver": {"type": "DummyImageQueryDriver"}, + "conversation_memory_driver": None, + "text_to_speech_driver": {"type": "DummyTextToSpeechDriver"}, + "audio_transcription_driver": {"type": "DummyAudioTranscriptionDriver"}, + "prompt_driver": { + "type": "CoherePromptDriver", + "temperature": 0.1, + "max_tokens": None, + "stream": False, + "model": "command-r", + }, + "embedding_driver": { + "type": "CohereEmbeddingDriver", + "model": "embed-english-v3.0", + "input_type": "search_document", + }, + "vector_store_driver": { + "type": "LocalVectorStoreDriver", + "embedding_driver": { + "type": "CohereEmbeddingDriver", + "model": "embed-english-v3.0", + "input_type": "search_document", + }, + }, + } diff --git a/tests/unit/drivers/embedding/test_cohere_embedding_driver.py b/tests/unit/drivers/embedding/test_cohere_embedding_driver.py new file mode 100644 index 000000000..af6a5576d --- /dev/null +++ b/tests/unit/drivers/embedding/test_cohere_embedding_driver.py @@ -0,0 +1,21 @@ +from unittest.mock import Mock +import pytest +from griptape.drivers import CohereEmbeddingDriver + + +class TestCohereEmbeddingDriver: + @pytest.fixture(autouse=True) + def mock_client(self, mocker): + mock_client = mocker.patch("cohere.Client").return_value + + mock_client.embed.return_value = Mock(embeddings=[[0, 1, 0]]) + + return mock_client + + def test_init(self): + assert CohereEmbeddingDriver(model="embed-english-v3.0", api_key="bar", input_type="search_document") + + def test_try_embed_chunk(self): + assert CohereEmbeddingDriver( + model="embed-english-v3.0", api_key="bar", input_type="search_document" + ).try_embed_chunk("foobar") == [0, 1, 0] diff --git a/tests/unit/drivers/embedding/test_sagemaker_embedding_driver.py b/tests/unit/drivers/embedding/test_sagemaker_embedding_driver.py deleted file mode 100644 index 9ceb98557..000000000 --- a/tests/unit/drivers/embedding/test_sagemaker_embedding_driver.py +++ /dev/null @@ -1,33 +0,0 @@ -import pytest -from unittest import mock -from griptape.drivers import AmazonSageMakerEmbeddingDriver, SageMakerHuggingFaceEmbeddingModelDriver -from griptape.tokenizers.openai_tokenizer import OpenAiTokenizer - - -class TestAmazonSagemakerEmbeddingDriver: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_embeddings = b'{"embedding": [[0, 1, 0]]}' - mock_session_class = mocker.patch("boto3.Session") - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_embeddings - mock_client.invoke_endpoint.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - def test_init(self): - assert AmazonSageMakerEmbeddingDriver( - model="test-endpoint", - tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), - embedding_model_driver=SageMakerHuggingFaceEmbeddingModelDriver(), - ) - - def test_try_embed_chunk(self): - assert AmazonSageMakerEmbeddingDriver( - model="test-endpoint", - tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), - embedding_model_driver=SageMakerHuggingFaceEmbeddingModelDriver(), - ).try_embed_chunk("foobar") == [0, 1, 0] diff --git a/tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py b/tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py new file mode 100644 index 000000000..268b47c54 --- /dev/null +++ b/tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py @@ -0,0 +1,59 @@ +import pytest +from unittest import mock +from griptape.drivers import AmazonSageMakerJumpstartEmbeddingDriver +from griptape.tokenizers.openai_tokenizer import OpenAiTokenizer + + +class TestAmazonSageMakerJumpstartEmbeddingDriver: + @pytest.fixture(autouse=True) + def mock_client(self, mocker): + mock_session_class = mocker.patch("boto3.Session") + mock_session_object = mock.Mock() + mock_client = mock.Mock() + mock_response = mock.Mock() + + mock_client.invoke_endpoint.return_value = mock_response + mock_session_object.client.return_value = mock_client + mock_session_class.return_value = mock_session_object + + return mock_response + + def test_init(self): + assert AmazonSageMakerJumpstartEmbeddingDriver( + endpoint="test-endpoint", + model="test-endpoint", + tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), + ) + + def test_try_embed_chunk(self, mock_client): + mock_client.get().read.return_value = b'{"embedding": [[0, 1, 0]]}' + assert AmazonSageMakerJumpstartEmbeddingDriver( + endpoint="test-endpoint", + model="test-model", + tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), + ).try_embed_chunk("foobar") == [0, 1, 0] + + mock_client.get().read.return_value = b'{"embedding": [0, 2, 0]}' + assert AmazonSageMakerJumpstartEmbeddingDriver( + endpoint="test-endpoint", + model="test-model", + tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), + ).try_embed_chunk("foobar") == [0, 2, 0] + + mock_client.get().read.return_value = b'{"embedding": []}' + with pytest.raises(ValueError) as e: + assert AmazonSageMakerJumpstartEmbeddingDriver( + endpoint="test-endpoint", + model="test-model", + tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), + ).try_embed_chunk("foobar") == [0, 2, 0] + assert str(e) == "model response is empty" + + mock_client.get().read.return_value = b"{}" + with pytest.raises(ValueError) as e: + assert AmazonSageMakerJumpstartEmbeddingDriver( + endpoint="test-endpoint", + model="test-model", + tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), + ).try_embed_chunk("foobar") == [0, 2, 0] + assert str(e) == "invalid response from model" diff --git a/tests/unit/drivers/embedding_model/__init__.py b/tests/unit/drivers/embedding_model/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/unit/drivers/embedding_model/test_sagemaker_huggingface_embedding_model_driver.py b/tests/unit/drivers/embedding_model/test_sagemaker_huggingface_embedding_model_driver.py deleted file mode 100644 index b63e593b3..000000000 --- a/tests/unit/drivers/embedding_model/test_sagemaker_huggingface_embedding_model_driver.py +++ /dev/null @@ -1,21 +0,0 @@ -import boto3 -import pytest -from griptape.drivers import AmazonSageMakerEmbeddingDriver, SageMakerHuggingFaceEmbeddingModelDriver -from tests.mocks.mock_tokenizer import MockTokenizer - - -class TestSageMakerHuggingFaceEmbeddingModelDriver: - @pytest.fixture - def driver(self): - return AmazonSageMakerEmbeddingDriver( - model="foo", - session=boto3.Session(region_name="us-east-1"), - tokenizer=MockTokenizer(model="foo"), - embedding_model_driver=SageMakerHuggingFaceEmbeddingModelDriver(), - ).embedding_model_driver - - def test_chunk_to_model_params(self, driver): - assert driver.chunk_to_model_params("foobar")["text_inputs"] == "foobar" - - def test_process_output(self, driver): - assert driver.process_output({"embedding": [["foobar"]]}) == ["foobar"] diff --git a/tests/unit/drivers/embedding_model/test_sagemaker_tensorflow_hub_embedding_model_driver.py b/tests/unit/drivers/embedding_model/test_sagemaker_tensorflow_hub_embedding_model_driver.py deleted file mode 100644 index 7080b93fb..000000000 --- a/tests/unit/drivers/embedding_model/test_sagemaker_tensorflow_hub_embedding_model_driver.py +++ /dev/null @@ -1,21 +0,0 @@ -import boto3 -import pytest -from griptape.drivers import AmazonSageMakerEmbeddingDriver, SageMakerTensorFlowHubEmbeddingModelDriver -from tests.mocks.mock_tokenizer import MockTokenizer - - -class TestSageMakerTensorFlowHubFaceEmbeddingModelDriver: - @pytest.fixture - def driver(self): - return AmazonSageMakerEmbeddingDriver( - model="foo", - session=boto3.Session(region_name="us-east-1"), - tokenizer=MockTokenizer(model="foo"), - embedding_model_driver=SageMakerTensorFlowHubEmbeddingModelDriver(), - ).embedding_model_driver - - def test_chunk_to_model_params(self, driver): - assert driver.chunk_to_model_params("foobar")["text_inputs"] == "foobar" - - def test_process_output(self, driver): - assert driver.process_output({"embedding": ["foobar"]}) == ["foobar"] diff --git a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py index 1bd94d3e9..8aa345595 100644 --- a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py @@ -1,117 +1,83 @@ -from botocore.response import StreamingBody -from griptape.artifacts import TextArtifact -from griptape.drivers import AmazonBedrockPromptDriver -from griptape.drivers import BedrockClaudePromptModelDriver, BedrockTitanPromptModelDriver -from griptape.tokenizers import AnthropicTokenizer, BedrockTitanTokenizer -from io import StringIO -from unittest.mock import Mock -import json import pytest +from griptape.utils import PromptStack +from griptape.drivers import AmazonBedrockPromptDriver + class TestAmazonBedrockPromptDriver: @pytest.fixture - def mock_prompt_model_driver(self): - mock_prompt_model_driver = Mock() - mock_prompt_model_driver.prompt_stack_to_model_params.return_value = {"model-param-key": "model-param-value"} - mock_prompt_model_driver.process_output.return_value = TextArtifact("model-output") - return mock_prompt_model_driver - - @pytest.fixture(autouse=True) - def mock_client(self, mocker): - return mocker.patch("boto3.Session").return_value.client.return_value - - def test_init(self): - assert AmazonBedrockPromptDriver(model="anthropic.claude", prompt_model_driver=BedrockClaudePromptModelDriver()) - - def test_custom_tokenizer(self): - assert isinstance( - AmazonBedrockPromptDriver( - model="anthropic.claude", prompt_model_driver=BedrockClaudePromptModelDriver() - ).tokenizer, - AnthropicTokenizer, - ) + def mock_converse(self, mocker): + mock_converse = mocker.patch("boto3.Session").return_value.client.return_value.converse - assert isinstance( - AmazonBedrockPromptDriver( - model="titan", - tokenizer=BedrockTitanTokenizer(model="amazon"), - prompt_model_driver=BedrockTitanPromptModelDriver(), - ).tokenizer, - BedrockTitanTokenizer, - ) + mock_converse.return_value = {"output": {"message": {"content": [{"text": "model-output"}]}}} + + return mock_converse + + @pytest.fixture + def mock_converse_stream(self, mocker): + mock_converse_stream = mocker.patch("boto3.Session").return_value.client.return_value.converse_stream + + mock_converse_stream.return_value = {"stream": [{"contentBlockDelta": {"delta": {"text": "model-output"}}}]} + + return mock_converse_stream + + @pytest.fixture + def prompt_stack(self): + prompt_stack = PromptStack() + prompt_stack.add_generic_input("generic-input") + prompt_stack.add_system_input("system-input") + prompt_stack.add_user_input("user-input") + prompt_stack.add_assistant_input("assistant-input") + + return prompt_stack - @pytest.mark.parametrize("model_inputs", [{"model-input-key": "model-input-value"}, "not-a-dict"]) - def test_try_run(self, model_inputs, mock_prompt_model_driver, mock_client): + @pytest.fixture + def messages(self): + return [ + {"role": "user", "content": [{"text": "generic-input"}]}, + {"role": "system", "content": [{"text": "system-input"}]}, + {"role": "user", "content": [{"text": "user-input"}]}, + {"role": "assistant", "content": [{"text": "assistant-input"}]}, + ] + + def test_try_run(self, mock_converse, prompt_stack, messages): # Given - driver = AmazonBedrockPromptDriver(model="model", prompt_model_driver=mock_prompt_model_driver) - prompt_stack = "prompt-stack" - response_body = "invoke-model-response-body" - mock_prompt_model_driver.prompt_stack_to_model_input.return_value = model_inputs - mock_client.invoke_model.return_value = {"body": to_streaming_body(response_body)} + driver = AmazonBedrockPromptDriver(model="ai21.j2") # When text_artifact = driver.try_run(prompt_stack) # Then - mock_prompt_model_driver.prompt_stack_to_model_input.assert_called_once_with(prompt_stack) - mock_prompt_model_driver.prompt_stack_to_model_params.assert_called_once_with(prompt_stack) - mock_client.invoke_model.assert_called_once_with( + mock_converse.assert_called_once_with( modelId=driver.model, - contentType="application/json", - accept="application/json", - body=json.dumps( - { - **mock_prompt_model_driver.prompt_stack_to_model_params.return_value, - **(model_inputs if isinstance(model_inputs, dict) else {}), - } - ), + messages=[ + {"role": "user", "content": [{"text": "generic-input"}]}, + {"role": "user", "content": [{"text": "user-input"}]}, + {"role": "assistant", "content": [{"text": "assistant-input"}]}, + ], + system=[{"text": "system-input"}], + inferenceConfig={"temperature": driver.temperature}, + additionalModelRequestFields={}, ) - mock_prompt_model_driver.process_output.assert_called_once_with(response_body) - assert text_artifact == mock_prompt_model_driver.process_output.return_value + assert text_artifact.value == "model-output" - @pytest.mark.parametrize("model_inputs", [{"model-input-key": "model-input-value"}, "not-a-dict"]) - def test_try_stream_run(self, model_inputs, mock_prompt_model_driver, mock_client): + def test_try_stream_run(self, mock_converse_stream, prompt_stack, messages): # Given - driver = AmazonBedrockPromptDriver(model="model", prompt_model_driver=mock_prompt_model_driver, stream=True) - prompt_stack = "prompt-stack" - model_response = "invoke-model-response-body" - response_body = [{"chunk": {"bytes": model_response}}] - mock_prompt_model_driver.prompt_stack_to_model_input.return_value = model_inputs - mock_client.invoke_model_with_response_stream.return_value = {"body": response_body} + driver = AmazonBedrockPromptDriver(model="ai21.j2", stream=True) # When text_artifact = next(driver.try_stream(prompt_stack)) # Then - mock_prompt_model_driver.prompt_stack_to_model_input.assert_called_once_with(prompt_stack) - mock_prompt_model_driver.prompt_stack_to_model_params.assert_called_once_with(prompt_stack) - mock_client.invoke_model_with_response_stream.assert_called_once_with( + mock_converse_stream.assert_called_once_with( modelId=driver.model, - contentType="application/json", - accept="application/json", - body=json.dumps( - { - **mock_prompt_model_driver.prompt_stack_to_model_params.return_value, - **(model_inputs if isinstance(model_inputs, dict) else {}), - } - ), + messages=[ + {"role": "user", "content": [{"text": "generic-input"}]}, + {"role": "user", "content": [{"text": "user-input"}]}, + {"role": "assistant", "content": [{"text": "assistant-input"}]}, + ], + system=[{"text": "system-input"}], + inferenceConfig={"temperature": driver.temperature}, + additionalModelRequestFields={}, ) - mock_prompt_model_driver.process_output.assert_called_once_with(model_response) - assert text_artifact.value == mock_prompt_model_driver.process_output.return_value.value - - def test_try_run_throws_on_empty_response(self, mock_prompt_model_driver, mock_client): - # Given - driver = AmazonBedrockPromptDriver(model="model", prompt_model_driver=mock_prompt_model_driver) - mock_client.invoke_model.return_value = {"body": to_streaming_body("")} - - # When - with pytest.raises(Exception) as e: - driver.try_run("prompt-stack") - - # Then - assert e.value.args[0] == "model response is empty" - - -def to_streaming_body(text: str) -> StreamingBody: - return StreamingBody(StringIO(text), len(text)) + assert text_artifact.value == "model-output" diff --git a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py new file mode 100644 index 000000000..4ae8fe944 --- /dev/null +++ b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py @@ -0,0 +1,132 @@ +from typing import Any +from botocore.response import StreamingBody +from griptape.tokenizers import HuggingFaceTokenizer +from griptape.drivers.prompt.amazon_sagemaker_jumpstart_prompt_driver import AmazonSageMakerJumpstartPromptDriver +from griptape.utils import PromptStack +from io import BytesIO +import json +import pytest + + +def to_streaming_body(data: Any) -> StreamingBody: + bytes = json.dumps(data).encode("utf-8") + + return StreamingBody(BytesIO(bytes), len(bytes)) + + +class TestAmazonSageMakerJumpstartPromptDriver: + @pytest.fixture(autouse=True) + def tokenizer(self, mocker): + from_pretrained = mocker.patch("transformers.AutoTokenizer").from_pretrained + from_pretrained.return_value.apply_chat_template.return_value = "foo\n\nUser: bar" + from_pretrained.return_value.model_max_length = 8000 + from_pretrained.return_value.eos_token_id = 1 + + return from_pretrained + + @pytest.fixture(autouse=True) + def mock_client(self, mocker): + return mocker.patch("boto3.Session").return_value.client.return_value + + def test_init(self): + assert AmazonSageMakerJumpstartPromptDriver(endpoint="foo", model="bar") + + def test_try_run(self, mock_client): + # Given + driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") + prompt_stack = PromptStack() + prompt_stack.add_user_input("prompt-stack") + + # When + response_body = [{"generated_text": "foobar"}] + mock_client.invoke_endpoint.return_value = {"Body": to_streaming_body(response_body)} + text_artifact = driver.try_run(prompt_stack) + assert isinstance(driver.tokenizer, HuggingFaceTokenizer) + + # Then + mock_client.invoke_endpoint.assert_called_with( + EndpointName=driver.endpoint, + ContentType="application/json", + Body=json.dumps( + { + "inputs": "foo\n\nUser: bar", + "parameters": { + "temperature": driver.temperature, + "max_new_tokens": 250, + "do_sample": True, + "eos_token_id": 1, + "stop_strings": [], + "return_full_text": False, + }, + } + ), + CustomAttributes="accept_eula=true", + ) + + assert text_artifact.value == "foobar" + + # When + response_body = {"generated_text": "foobar"} + mock_client.invoke_endpoint.return_value = {"Body": to_streaming_body(response_body)} + text_artifact = driver.try_run(prompt_stack) + assert isinstance(driver.tokenizer, HuggingFaceTokenizer) + + # Then + mock_client.invoke_endpoint.assert_called_with( + EndpointName=driver.endpoint, + ContentType="application/json", + Body=json.dumps( + { + "inputs": "foo\n\nUser: bar", + "parameters": { + "temperature": driver.temperature, + "max_new_tokens": 250, + "do_sample": True, + "eos_token_id": 1, + "stop_strings": [], + "return_full_text": False, + }, + } + ), + CustomAttributes="accept_eula=true", + ) + + assert text_artifact.value == "foobar" + + def test_try_stream(self, mock_client): + # Given + driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") + prompt_stack = PromptStack() + prompt_stack.add_user_input("prompt-stack") + + # When + with pytest.raises(NotImplementedError) as e: + driver.try_stream(prompt_stack) + + # Then + assert e.value.args[0] == "streaming is not supported" + + def test_stream_init(self): + # Given + driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") + + # When + with pytest.raises(ValueError) as e: + driver.stream = True + + # Then + assert e.value.args[0] == "streaming is not supported" + + def test_try_run_throws_on_empty_response(self, mock_client): + # Given + driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") + mock_client.invoke_endpoint.return_value = {"Body": to_streaming_body([])} + prompt_stack = PromptStack() + prompt_stack.add_user_input("prompt-stack") + + # When + with pytest.raises(Exception) as e: + driver.try_run(prompt_stack) + + # Then + assert e.value.args[0] == "model response is empty" diff --git a/tests/unit/drivers/prompt/test_amazon_sagemaker_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_sagemaker_prompt_driver.py deleted file mode 100644 index c6692e1ba..000000000 --- a/tests/unit/drivers/prompt/test_amazon_sagemaker_prompt_driver.py +++ /dev/null @@ -1,90 +0,0 @@ -from botocore.response import StreamingBody -from griptape.artifacts import TextArtifact -from griptape.drivers import AmazonSageMakerPromptDriver, SageMakerFalconPromptModelDriver -from griptape.tokenizers import HuggingFaceTokenizer, OpenAiTokenizer -from griptape.utils import PromptStack -from io import BytesIO -from unittest.mock import Mock -import json -import pytest - - -class TestAmazonSageMakerPromptDriver: - @pytest.fixture - def mock_model_driver(self): - mock_model_driver = Mock() - mock_model_driver.prompt_stack_to_model_input.return_value = "model-inputs" - mock_model_driver.prompt_stack_to_model_params.return_value = "model-params" - mock_model_driver.process_output.return_value = TextArtifact("model-output") - return mock_model_driver - - @pytest.fixture(autouse=True) - def mock_client(self, mocker): - return mocker.patch("boto3.Session").return_value.client.return_value - - def test_init(self): - assert AmazonSageMakerPromptDriver(endpoint="foo", prompt_model_driver=SageMakerFalconPromptModelDriver()) - - def test_custom_tokenizer(self): - assert isinstance( - AmazonSageMakerPromptDriver( - endpoint="foo", prompt_model_driver=SageMakerFalconPromptModelDriver() - ).tokenizer, - HuggingFaceTokenizer, - ) - - assert isinstance( - AmazonSageMakerPromptDriver( - endpoint="foo", - tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), - prompt_model_driver=SageMakerFalconPromptModelDriver(), - ).tokenizer, - OpenAiTokenizer, - ) - - def test_try_run(self, mock_model_driver, mock_client): - # Given - driver = AmazonSageMakerPromptDriver(endpoint="model", prompt_model_driver=mock_model_driver) - prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") - response_body = "invoke-endpoint-response-body" - mock_client.invoke_endpoint.return_value = {"Body": to_streaming_body(response_body)} - - # When - text_artifact = driver.try_run(prompt_stack) - - # Then - mock_model_driver.prompt_stack_to_model_input.assert_called_once_with(prompt_stack) - mock_model_driver.prompt_stack_to_model_params.assert_called_once_with(prompt_stack) - mock_client.invoke_endpoint.assert_called_once_with( - EndpointName=driver.endpoint, - ContentType="application/json", - Body=json.dumps( - { - "inputs": mock_model_driver.prompt_stack_to_model_input.return_value, - "parameters": mock_model_driver.prompt_stack_to_model_params.return_value, - } - ), - CustomAttributes="accept_eula=true", - ) - mock_model_driver.process_output.assert_called_once_with(response_body) - assert text_artifact == mock_model_driver.process_output.return_value - - def test_try_run_throws_on_empty_response(self, mock_model_driver, mock_client): - # Given - driver = AmazonSageMakerPromptDriver(endpoint="model", prompt_model_driver=mock_model_driver) - mock_client.invoke_endpoint.return_value = {"Body": to_streaming_body("")} - prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") - - # When - with pytest.raises(Exception) as e: - driver.try_run(prompt_stack) - - # Then - assert e.value.args[0] == "model response is empty" - - -def to_streaming_body(text: str) -> StreamingBody: - bytes = json.dumps(text).encode("utf-8") - return StreamingBody(BytesIO(bytes), len(bytes)) diff --git a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py index c5009afac..22178bbf3 100644 --- a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py @@ -63,9 +63,9 @@ def test_try_run(self, mock_client, model, system_enabled): # Then mock_client.return_value.messages.create.assert_called_once_with( messages=expected_messages, - stop_sequences=["<|Response|>"], + stop_sequences=[], model=driver.model, - max_tokens=4091, + max_tokens=1000, temperature=0.1, top_p=0.999, top_k=250, @@ -106,9 +106,9 @@ def test_try_stream_run(self, mock_stream_client, model, system_enabled): # Then mock_stream_client.return_value.messages.create.assert_called_once_with( messages=expected_messages, - stop_sequences=["<|Response|>"], + stop_sequences=[], model=driver.model, - max_tokens=4091, + max_tokens=1000, temperature=0.1, stream=True, top_p=0.999, diff --git a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py index 9446d0520..f6bd12d80 100644 --- a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py @@ -7,11 +7,11 @@ class TestAzureOpenAiChatPromptDriver(TestOpenAiChatPromptDriverFixtureMixin): @pytest.fixture def mock_chat_completion_create(self, mocker): - mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.with_raw_response.create + mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create mock_choice = Mock() mock_choice.message.content = "model-output" mock_chat_create.return_value.headers = {} - mock_chat_create.return_value.parse.return_value.choices = [mock_choice] + mock_chat_create.return_value.choices = [mock_choice] return mock_chat_create @pytest.fixture diff --git a/tests/unit/drivers/prompt/test_azure_openai_completion_prompt_driver.py b/tests/unit/drivers/prompt/test_azure_openai_completion_prompt_driver.py deleted file mode 100644 index 65758843a..000000000 --- a/tests/unit/drivers/prompt/test_azure_openai_completion_prompt_driver.py +++ /dev/null @@ -1,75 +0,0 @@ -import pytest -from unittest.mock import Mock -from griptape.drivers import AzureOpenAiCompletionPromptDriver -from tests.unit.drivers.prompt.test_openai_completion_prompt_driver import TestOpenAiCompletionPromptDriverFixtureMixin -from unittest.mock import ANY - - -class TestAzureOpenAiCompletionPromptDriver(TestOpenAiCompletionPromptDriverFixtureMixin): - @pytest.fixture - def mock_completion_create(self, mocker): - mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.completions.create - mock_choice = Mock() - mock_choice.text = "model-output" - mock_chat_create.return_value.choices = [mock_choice] - return mock_chat_create - - @pytest.fixture - def mock_completion_stream_create(self, mocker): - mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.completions.create - mock_chunk = Mock() - mock_choice = Mock() - mock_choice.text = "model-output" - mock_chunk.choices = [mock_choice] - mock_chat_create.return_value = iter([mock_chunk]) - return mock_chat_create - - def test_init(self): - assert AzureOpenAiCompletionPromptDriver( - azure_endpoint="endpoint", azure_deployment="deployment", model="text-davinci-003" - ) - assert ( - AzureOpenAiCompletionPromptDriver(azure_endpoint="endpoint", model="text-davinci-003").azure_deployment - == "text-davinci-003" - ) - - def test_try_run(self, mock_completion_create, prompt_stack, prompt): - # Given - driver = AzureOpenAiCompletionPromptDriver( - azure_endpoint="endpoint", azure_deployment="deployment", model="text-davinci-003" - ) - - # When - text_artifact = driver.try_run(prompt_stack) - - # Then - mock_completion_create.assert_called_once_with( - model=driver.model, - max_tokens=ANY, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - prompt=prompt, - ) - assert text_artifact.value == "model-output" - - def test_try_stream_run(self, mock_completion_stream_create, prompt_stack, prompt): - # Given - driver = AzureOpenAiCompletionPromptDriver( - azure_endpoint="endpoint", azure_deployment="deployment", model="text-davinci-003", stream=True - ) - - # When - text_artifact = next(driver.try_stream(prompt_stack)) - - # Then - mock_completion_stream_create.assert_called_once_with( - model=driver.model, - max_tokens=ANY, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - stream=True, - prompt=prompt, - ) - assert text_artifact.value == "model-output" diff --git a/tests/unit/drivers/prompt/test_base_prompt_driver.py b/tests/unit/drivers/prompt/test_base_prompt_driver.py index 1a06b5907..0743402aa 100644 --- a/tests/unit/drivers/prompt/test_base_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_base_prompt_driver.py @@ -39,35 +39,6 @@ def test_run_via_pipeline_publishes_events(self, mocker): def test_run(self): assert isinstance(MockPromptDriver().run(PromptStack(inputs=[])), TextArtifact) - def test_token_count(self): - assert ( - MockPromptDriver().token_count( - PromptStack(inputs=[PromptStack.Input("foobar", role=PromptStack.USER_ROLE)]) - ) - == 24 - ) - - def test_max_output_tokens(self): - assert MockPromptDriver().max_output_tokens("foobar") == 4090 - assert MockPromptDriver(max_tokens=5000).max_output_tokens("foobar") == 4090 - assert MockPromptDriver(max_tokens=100).max_output_tokens("foobar") == 100 - - def test_prompt_stack_to_string(self): - assert ( - MockPromptDriver().prompt_stack_to_string( - PromptStack(inputs=[PromptStack.Input("foobar", role=PromptStack.USER_ROLE)]) - ) - == "User: foobar\n\nAssistant:" - ) - - def test_custom_prompt_stack_to_string(self): - assert ( - MockPromptDriver( - prompt_stack_to_string=lambda stack: f"Foo: {stack.inputs[0].content}" - ).prompt_stack_to_string(PromptStack(inputs=[PromptStack.Input("foobar", role=PromptStack.USER_ROLE)])) - == "Foo: foobar" - ) - def instance_count(instances, clazz): return len([instance for instance in instances if isinstance(instance, clazz)]) diff --git a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py index 907e27325..b3ceb11a4 100644 --- a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py @@ -8,16 +8,16 @@ class TestCoherePromptDriver: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value - mock_client.generate.return_value.generations = [Mock()] - mock_client.generate.return_value.generations[0].text = "model-output" + mock_client.chat.return_value = Mock(text="model-output") + return mock_client @pytest.fixture def mock_stream_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value - mock_chunk = Mock() - mock_chunk.text = "model-output" - mock_client.generate.return_value = iter([mock_chunk]) + mock_chunk = Mock(text="model-output", event_type="text-generation") + mock_client.chat_stream.return_value = iter([mock_chunk]) + return mock_client @pytest.fixture(autouse=True) @@ -55,16 +55,3 @@ def test_try_stream_run(self, mock_stream_client, prompt_stack): # pyright: ign # Then assert text_artifact.value == "model-output" - - @pytest.mark.parametrize("choices", [[], [1, 2]]) - def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_client, prompt_stack): - # Given - driver = CoherePromptDriver(model="command", api_key="api-key") - mock_client.generate.return_value.generations = choices - - # When - with pytest.raises(Exception) as e: - driver.try_run(prompt_stack) - - # Then - e.value.args[0] == "Completion with more than one choice is not supported yet." diff --git a/tests/unit/drivers/prompt/test_google_prompt_driver.py b/tests/unit/drivers/prompt/test_google_prompt_driver.py index 6e38bd503..f655d3e51 100644 --- a/tests/unit/drivers/prompt/test_google_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_google_prompt_driver.py @@ -2,7 +2,6 @@ from griptape.drivers import GooglePromptDriver from griptape.utils import PromptStack from unittest.mock import Mock -from tests.mocks.mock_tokenizer import MockTokenizer import pytest @@ -32,9 +31,7 @@ def test_try_run(self, mock_generative_model): prompt_stack.add_user_input("user-input") prompt_stack.add_assistant_input("assistant-input") prompt_stack.add_generic_input("generic-input") - driver = GooglePromptDriver( - model="gemini-pro", api_key="api-key", tokenizer=MockTokenizer(model="gemini-pro"), top_p=0.5, top_k=50 - ) + driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", top_p=0.5, top_k=50) # When text_artifact = driver.try_run(prompt_stack) @@ -47,7 +44,7 @@ def test_try_run(self, mock_generative_model): {"parts": ["generic-input"], "role": "user"}, ], generation_config=GenerationConfig( - max_output_tokens=997, temperature=0.1, top_p=0.5, top_k=50, stop_sequences=["<|Response|>"] + max_output_tokens=None, temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[] ), ) assert text_artifact.value == "model-output" @@ -59,14 +56,7 @@ def test_try_stream(self, mock_stream_generative_model): prompt_stack.add_user_input("user-input") prompt_stack.add_assistant_input("assistant-input") prompt_stack.add_generic_input("generic-input") - driver = GooglePromptDriver( - model="gemini-pro", - api_key="api-key", - stream=True, - tokenizer=MockTokenizer(model="gemini-pro"), - top_p=0.5, - top_k=50, - ) + driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", stream=True, top_p=0.5, top_k=50) # When text_artifact_stream = driver.try_stream(prompt_stack) @@ -80,9 +70,7 @@ def test_try_stream(self, mock_stream_generative_model): {"parts": ["generic-input"], "role": "user"}, ], stream=True, - generation_config=GenerationConfig( - max_output_tokens=997, temperature=0.1, top_p=0.5, top_k=50, stop_sequences=["<|Response|>"] - ), + generation_config=GenerationConfig(temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[]), ) assert text_artifact.value == "model-output" @@ -108,26 +96,3 @@ def test_prompt_stack_to_model_input(self): {"role": "model", "parts": ["assistant-input"]}, {"role": "user", "parts": ["user-input"]}, ] - - def test_to_content_dict(self): - # Given - driver = GooglePromptDriver(model="gemini-pro", api_key="1234") - - # When - assert driver._GooglePromptDriver__to_content_dict(PromptStack.Input("system-input", "system")) == { - "role": "user", - "parts": ["system-input"], - } - assert driver._GooglePromptDriver__to_content_dict(PromptStack.Input("user-input", "user")) == { - "role": "user", - "parts": ["user-input"], - } - assert driver._GooglePromptDriver__to_content_dict(PromptStack.Input("assistant-input", "assistant")) == { - "role": "model", - "parts": ["assistant-input"], - } - - assert driver._GooglePromptDriver__to_content_dict(PromptStack.Input("generic-input", "generic")) == { - "role": "user", - "parts": ["generic-input"], - } diff --git a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py index 6b91b56cb..15bbb4ead 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py @@ -10,6 +10,13 @@ def mock_client(self, mocker): mock_client.text_generation.return_value = "model-output" return mock_client + @pytest.fixture(autouse=True) + def tokenizer(self, mocker): + from_pretrained = tokenizer = mocker.patch("transformers.AutoTokenizer").from_pretrained + from_pretrained.return_value.apply_chat_template.return_value = [1, 2, 3] + + return tokenizer + @pytest.fixture def mock_client_stream(self, mocker): mock_client = mocker.patch("huggingface_hub.InferenceClient").return_value diff --git a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py index fec39da4d..b2746ca58 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py @@ -13,13 +13,15 @@ def mock_pipeline(self, mocker): def mock_generator(self, mock_pipeline): mock_generator = mock_pipeline.return_value mock_generator.task = "text-generation" - mock_generator.return_value = [{"generated_text": "model-output"}] + mock_generator.return_value = [{"generated_text": [{"content": "model-output"}]}] return mock_generator @pytest.fixture(autouse=True) def mock_autotokenizer(self, mocker): mock_autotokenizer = mocker.patch("transformers.AutoTokenizer.from_pretrained").return_value mock_autotokenizer.model_max_length = 42 + mock_autotokenizer.apply_chat_template.return_value = [1, 2, 3] + mock_autotokenizer.decode.return_value = "model-output" return mock_autotokenizer @pytest.fixture @@ -44,6 +46,16 @@ def test_try_run(self, prompt_stack): # Then assert text_artifact.value == "model-output" + def test_try_stream(self, prompt_stack): + # Given + driver = HuggingFacePipelinePromptDriver(model="foo", max_tokens=42) + + # When + with pytest.raises(Exception) as e: + driver.try_stream(prompt_stack) + + assert e.value.args[0] == "streaming is not supported" + @pytest.mark.parametrize("choices", [[], [1, 2]]) def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_generator, prompt_stack): # Given @@ -55,16 +67,26 @@ def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_gener driver.try_run(prompt_stack) # Then - e.value.args[0] == "completion with more than one choice is not supported yet" + assert e.value.args[0] == "completion with more than one choice is not supported yet" - def test_try_run_throws_when_unsupported_task_returned(self, prompt_stack, mock_generator): + def test_try_run_throws_when_non_list(self, mock_generator, prompt_stack): # Given driver = HuggingFacePipelinePromptDriver(model="foo", max_tokens=42) - mock_generator.task = "obviously-an-unsupported-task" + mock_generator.return_value = {} # When with pytest.raises(Exception) as e: driver.try_run(prompt_stack) # Then - assert e.value.args[0].startswith("only models with the following tasks are supported: ") + assert e.value.args[0] == "invalid output format" + + def test_prompt_stack_to_string(self, prompt_stack): + # Given + driver = HuggingFacePipelinePromptDriver(model="foo", max_tokens=42) + + # When + result = driver.prompt_stack_to_string(prompt_stack) + + # Then + assert result == "model-output" diff --git a/tests/unit/drivers/prompt/test_ollama_prompt_driver.py b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py new file mode 100644 index 000000000..d42a8b45d --- /dev/null +++ b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py @@ -0,0 +1,96 @@ +from griptape.drivers import OllamaPromptDriver +from griptape.utils import PromptStack +import pytest + + +class TestOllamaPromptDriver: + @pytest.fixture + def mock_client(self, mocker): + mock_client = mocker.patch("ollama.Client") + + mock_client.return_value.chat.return_value = {"message": {"content": "model-output"}} + + return mock_client + + @pytest.fixture + def mock_stream_client(self, mocker): + mock_stream_client = mocker.patch("ollama.Client") + mock_stream_client.return_value.chat.return_value = iter([{"message": {"content": "model-output"}}]) + + return mock_stream_client + + def test_init(self): + assert OllamaPromptDriver(model="llama") + + def test_try_run(self, mock_client): + # Given + prompt_stack = PromptStack() + prompt_stack.add_generic_input("generic-input") + prompt_stack.add_system_input("system-input") + prompt_stack.add_user_input("user-input") + prompt_stack.add_assistant_input("assistant-input") + driver = OllamaPromptDriver(model="llama") + expected_messages = [ + {"role": "generic", "content": "generic-input"}, + {"role": "system", "content": "system-input"}, + {"role": "user", "content": "user-input"}, + {"role": "assistant", "content": "assistant-input"}, + ] + + # When + text_artifact = driver.try_run(prompt_stack) + + # Then + mock_client.return_value.chat.assert_called_once_with( + messages=expected_messages, + model=driver.model, + options={"temperature": driver.temperature, "stop": [], "num_predict": driver.max_tokens}, + ) + assert text_artifact.value == "model-output" + + def test_try_run_bad_response(self, mock_client): + # Given + prompt_stack = PromptStack() + driver = OllamaPromptDriver(model="llama") + mock_client.return_value.chat.return_value = "bad-response" + + # When/Then + with pytest.raises(Exception, match="invalid model response"): + driver.try_run(prompt_stack) + + def test_try_stream_run(self, mock_stream_client): + # Given + prompt_stack = PromptStack() + prompt_stack.add_generic_input("generic-input") + prompt_stack.add_system_input("system-input") + prompt_stack.add_user_input("user-input") + prompt_stack.add_assistant_input("assistant-input") + expected_messages = [ + {"role": "generic", "content": "generic-input"}, + {"role": "system", "content": "system-input"}, + {"role": "user", "content": "user-input"}, + {"role": "assistant", "content": "assistant-input"}, + ] + driver = OllamaPromptDriver(model="llama", stream=True) + + # When + text_artifact = next(driver.try_stream(prompt_stack)) + + # Then + mock_stream_client.return_value.chat.assert_called_once_with( + messages=expected_messages, + model=driver.model, + options={"temperature": driver.temperature, "stop": [], "num_predict": driver.max_tokens}, + stream=True, + ) + assert text_artifact.value == "model-output" + + def test_try_stream_bad_response(self, mock_stream_client): + # Given + prompt_stack = PromptStack() + driver = OllamaPromptDriver(model="llama", stream=True) + mock_stream_client.return_value.chat.return_value = "bad-response" + + # When/Then + with pytest.raises(Exception, match="invalid model response"): + next(driver.try_stream(prompt_stack)) diff --git a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py index fbc939005..a2900d4d3 100644 --- a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py @@ -1,7 +1,3 @@ -import datetime - -from transformers import AutoTokenizer - from griptape.drivers import OpenAiChatPromptDriver from griptape.tokenizers.huggingface_tokenizer import HuggingFaceTokenizer from griptape.utils import PromptStack @@ -13,11 +9,11 @@ class TestOpenAiChatPromptDriverFixtureMixin: @pytest.fixture def mock_chat_completion_create(self, mocker): - mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.with_raw_response.create + mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create mock_choice = Mock() mock_choice.message.content = "model-output" mock_chat_create.return_value.headers = {} - mock_chat_create.return_value.parse.return_value.choices = [mock_choice] + mock_chat_create.return_value.choices = [mock_choice] return mock_chat_create @pytest.fixture @@ -163,30 +159,6 @@ def test_try_run_with_max_tokens(self, mock_chat_completion_create, prompt_stack ) assert text_artifact.value == "model-output" - def test_try_run_max_tokens_limited_by_tokenizer(self, mock_chat_completion_create, prompt_stack, messages): - # Given - max_tokens_request = 9999999 - driver = OpenAiChatPromptDriver( - model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, max_tokens=max_tokens_request - ) - tokens_left = driver.tokenizer.count_input_tokens_left(driver._prompt_stack_to_messages(prompt_stack)) - - # When - text_artifact = driver.try_run(prompt_stack) - - # Then - mock_chat_completion_create.assert_called_once_with( - model=driver.model, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - messages=messages, - max_tokens=max_tokens_request, - seed=driver.seed, - ) - assert max_tokens_request > tokens_left - assert text_artifact.value == "model-output" - def test_try_run_throws_when_prompt_stack_is_string(self): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) @@ -202,7 +174,7 @@ def test_try_run_throws_when_prompt_stack_is_string(self): def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_chat_completion_create, prompt_stack): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, api_key="api-key") - mock_chat_completion_create.return_value.parse.return_value.choices = [choices] + mock_chat_completion_create.return_value.choices = [choices] # When with pytest.raises(Exception) as e: @@ -211,116 +183,10 @@ def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_chat_ # Then e.value.args[0] == "Completion with more than one choice is not supported yet." - def test_token_count(self, prompt_stack, messages): - # Given - mock_tokenizer = Mock(spec=OpenAiTokenizer) - mock_tokenizer.count_tokens.return_value = 42 - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, tokenizer=mock_tokenizer) - - # When - token_count = driver.token_count(prompt_stack) - - # Then - mock_tokenizer.count_tokens.assert_called_once_with(messages) - assert token_count == 42 - - # Given - mock_tokenizer = Mock() - mock_tokenizer.count_tokens.return_value = 42 - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, tokenizer=mock_tokenizer) - - # When - token_count = driver.token_count(prompt_stack) - - # Then - mock_tokenizer.count_tokens.assert_called_once_with(driver.prompt_stack_to_string(prompt_stack)) - assert token_count == 42 - - def test_max_output_tokens(self, messages): - # Given - mock_tokenizer = Mock() - mock_tokenizer.count_output_tokens_left.return_value = 42 - driver = OpenAiChatPromptDriver( - model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, tokenizer=mock_tokenizer, max_tokens=45 - ) - - # When - max_output_tokens = driver.max_output_tokens(messages) - - # Then - mock_tokenizer.count_output_tokens_left.assert_called_once_with(messages) - assert max_output_tokens == 42 - - def test_max_output_tokens_with_max_tokens(self, messages): - max_tokens = OpenAiChatPromptDriver( - model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, max_tokens=42 - ).max_output_tokens(messages) - - assert max_tokens == 42 - - def test_extract_ratelimit_metadata(self): - response_with_headers = OpenAiApiResponseWithHeaders() - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - driver._extract_ratelimit_metadata(response_with_headers) - - assert driver._ratelimit_requests_remaining == response_with_headers.remaining_requests - assert driver._ratelimit_tokens_remaining == response_with_headers.remaining_tokens - assert driver._ratelimit_request_limit == response_with_headers.limit_requests - assert driver._ratelimit_token_limit == response_with_headers.limit_tokens - - # Assert that the reset times are within one second of the expected value. - expected_request_reset_time = datetime.datetime.now() + datetime.timedelta( - seconds=response_with_headers.reset_requests_in - ) - expected_token_reset_time = datetime.datetime.now() + datetime.timedelta( - seconds=response_with_headers.reset_tokens_in - ) - - assert driver._ratelimit_requests_reset_at is not None - assert abs(driver._ratelimit_requests_reset_at - expected_request_reset_time) < datetime.timedelta(seconds=1) - assert driver._ratelimit_tokens_reset_at is not None - assert abs(driver._ratelimit_tokens_reset_at - expected_token_reset_time) < datetime.timedelta(seconds=1) - - def test_extract_ratelimit_metadata_with_subsecond_reset_times(self): - response_with_headers = OpenAiApiResponseWithHeaders( - reset_requests_in=1, reset_requests_in_unit="ms", reset_tokens_in=10, reset_tokens_in_unit="ms" - ) - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, api_key="api-key") - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - driver._extract_ratelimit_metadata(response_with_headers) - - # Assert that the reset times are within one second of the expected value. With a sub-second reset time, - # this is rounded up to one second in the future. - expected_request_reset_time = datetime.datetime.now() + datetime.timedelta(seconds=1) - expected_token_reset_time = datetime.datetime.now() + datetime.timedelta(seconds=1) - - assert driver._ratelimit_requests_reset_at is not None - assert abs(driver._ratelimit_requests_reset_at - expected_request_reset_time) < datetime.timedelta(seconds=1) - assert driver._ratelimit_tokens_reset_at is not None - assert abs(driver._ratelimit_tokens_reset_at - expected_token_reset_time) < datetime.timedelta(seconds=1) - - def test_extract_ratelimit_metadata_missing_headers(self): - class OpenAiApiResponseNoHeaders: - @property - def headers(self): - return {} - - response_without_headers = OpenAiApiResponseNoHeaders() - - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - driver._extract_ratelimit_metadata(response_without_headers) - - assert driver._ratelimit_request_limit is None - assert driver._ratelimit_requests_remaining is None - assert driver._ratelimit_requests_reset_at is None - assert driver._ratelimit_token_limit is None - assert driver._ratelimit_tokens_remaining is None - assert driver._ratelimit_tokens_reset_at is None - def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messages): driver = OpenAiChatPromptDriver( model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, - tokenizer=HuggingFaceTokenizer(tokenizer=AutoTokenizer.from_pretrained("gpt2"), max_output_tokens=1000), + tokenizer=HuggingFaceTokenizer(model="gpt2", max_output_tokens=1000), max_tokens=1, ) @@ -333,7 +199,12 @@ def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messa temperature=driver.temperature, stop=driver.tokenizer.stop_sequences, user=driver.user, - messages=messages, + messages=[ + {"role": "user", "content": "generic-input"}, + {"role": "system", "content": "system-input"}, + {"role": "user", "content": "user-input"}, + {"role": "assistant", "content": "assistant-input"}, + ], seed=driver.seed, max_tokens=1, ) diff --git a/tests/unit/drivers/prompt/test_openai_completion_prompt_driver.py b/tests/unit/drivers/prompt/test_openai_completion_prompt_driver.py deleted file mode 100644 index 66998c261..000000000 --- a/tests/unit/drivers/prompt/test_openai_completion_prompt_driver.py +++ /dev/null @@ -1,112 +0,0 @@ -from griptape.drivers import OpenAiCompletionPromptDriver -from griptape.utils import PromptStack -from unittest.mock import ANY, Mock -from griptape.tokenizers import OpenAiTokenizer -import pytest - - -class TestOpenAiCompletionPromptDriverFixtureMixin: - @pytest.fixture - def mock_completion_create(self, mocker): - mock_chat_create = mocker.patch("openai.OpenAI").return_value.completions.create - mock_choice = Mock() - mock_choice.text = "model-output" - mock_chat_create.return_value.choices = [mock_choice] - return mock_chat_create - - @pytest.fixture - def mock_completion_stream_create(self, mocker): - mock_chat_create = mocker.patch("openai.OpenAI").return_value.completions.create - mock_chunk = Mock() - mock_choice = Mock() - mock_choice.text = "model-output" - mock_chunk.choices = [mock_choice] - mock_chat_create.return_value = iter([mock_chunk]) - return mock_chat_create - - @pytest.fixture - def prompt_stack(self): - prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") - return prompt_stack - - @pytest.fixture - def prompt(self): - return "".join( - [ - "generic-input\n\n", - "system-input\n\n", - "User: user-input\n\n", - "Assistant: assistant-input\n\n", - "Assistant:", - ] - ) - - -class TestOpenAiCompletionPromptDriver(TestOpenAiCompletionPromptDriverFixtureMixin): - def test_init(self): - assert OpenAiCompletionPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - - def test_try_run(self, mock_completion_create, prompt_stack, prompt): - # Given - driver = OpenAiCompletionPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - - # When - text_artifact = driver.try_run(prompt_stack) - - # Then - mock_completion_create.assert_called_once_with( - model=driver.model, - max_tokens=ANY, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - prompt=prompt, - ) - assert text_artifact.value == "model-output" - - def test_try_stream_run(self, mock_completion_stream_create, prompt_stack, prompt): - # Given - driver = OpenAiCompletionPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, stream=True) - - # When - text_artifact = next(driver.try_stream(prompt_stack)) - - # Then - mock_completion_stream_create.assert_called_once_with( - model=driver.model, - max_tokens=ANY, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - stream=True, - prompt=prompt, - ) - assert text_artifact.value == "model-output" - - def test_try_run_throws_when_prompt_stack_is_string(self): - # Given - driver = OpenAiCompletionPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - - # When - with pytest.raises(Exception) as e: - driver.try_run("prompt-stack") # pyright: ignore - - # Then - assert e.value.args[0] == "'str' object has no attribute 'inputs'" - - @pytest.mark.parametrize("choices", [[], [1, 2]]) - def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_completion_create, prompt_stack): - # Given - driver = OpenAiCompletionPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - mock_completion_create.return_value.choices = choices - - # When - with pytest.raises(Exception) as e: - driver.try_run(prompt_stack) - - # Then - e.value.args[0] == "Completion with more than one choice is not supported yet." diff --git a/tests/unit/drivers/prompt_models/__init__.py b/tests/unit/drivers/prompt_models/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/unit/drivers/prompt_models/test_bedrock_claude_prompt_model_driver.py b/tests/unit/drivers/prompt_models/test_bedrock_claude_prompt_model_driver.py deleted file mode 100644 index 94bc97122..000000000 --- a/tests/unit/drivers/prompt_models/test_bedrock_claude_prompt_model_driver.py +++ /dev/null @@ -1,129 +0,0 @@ -from unittest import mock -import json -import boto3 -import pytest -from griptape.utils import PromptStack -from griptape.drivers import AmazonBedrockPromptDriver, BedrockClaudePromptModelDriver - - -class TestBedrockClaudePromptModelDriver: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - @pytest.fixture - def driver(self, request): - return AmazonBedrockPromptDriver( - model=request.param, - session=boto3.Session(region_name="us-east-1"), - prompt_model_driver=BedrockClaudePromptModelDriver(), - temperature=0.12345, - ).prompt_model_driver - - @pytest.mark.parametrize( - "driver,", - [ - ("anthropic.claude-v2"), - ("anthropic.claude-v2:1"), - ("anthropic.claude-3-sonnet-20240229-v1:0"), - ("anthropic.claude-3-haiku-20240307-v1:0"), - ], - indirect=["driver"], - ) - def test_init(self, driver): - assert driver.prompt_driver is not None - - @pytest.mark.parametrize( - "driver,", - [ - ("anthropic.claude-v2"), - ("anthropic.claude-v2:1"), - ("anthropic.claude-3-sonnet-20240229-v1:0"), - ("anthropic.claude-3-haiku-20240307-v1:0"), - ], - indirect=["driver"], - ) - @pytest.mark.parametrize("system_enabled", [True, False]) - def test_prompt_stack_to_model_input(self, driver, system_enabled): - stack = PromptStack() - if system_enabled: - stack.add_system_input("foo") - stack.add_user_input("bar") - stack.add_assistant_input("baz") - stack.add_generic_input("qux") - - expected_messages = [ - {"role": "user", "content": "bar"}, - {"role": "assistant", "content": "baz"}, - {"role": "user", "content": "qux"}, - ] - actual = driver.prompt_stack_to_model_input(stack) - expected = {"messages": expected_messages, **({"system": "foo"} if system_enabled else {})} - - assert actual == expected - - @pytest.mark.parametrize( - "driver,", - [ - ("anthropic.claude-v2"), - ("anthropic.claude-v2:1"), - ("anthropic.claude-3-sonnet-20240229-v1:0"), - ("anthropic.claude-3-haiku-20240307-v1:0"), - ], - indirect=["driver"], - ) - @pytest.mark.parametrize("system_enabled", [True, False]) - def test_prompt_stack_to_model_params(self, driver, system_enabled): - stack = PromptStack() - if system_enabled: - stack.add_system_input("foo") - stack.add_user_input("bar") - stack.add_assistant_input("baz") - stack.add_generic_input("qux") - - max_tokens = driver.prompt_driver.max_output_tokens(driver.prompt_driver.prompt_stack_to_string(stack)) - - expected = { - "temperature": 0.12345, - "max_tokens": max_tokens, - "anthropic_version": driver.ANTHROPIC_VERSION, - "messages": [ - {"role": "user", "content": "bar"}, - {"role": "assistant", "content": "baz"}, - {"role": "user", "content": "qux"}, - ], - "top_p": 0.999, - "top_k": 250, - "stop_sequences": ["<|Response|>"], - **({"system": "foo"} if system_enabled else {}), - } - - assert driver.prompt_stack_to_model_params(stack) == expected - - @pytest.mark.parametrize( - "driver,", - [ - ("anthropic.claude-v2"), - ("anthropic.claude-v2:1"), - ("anthropic.claude-3-sonnet-20240229-v1:0"), - ("anthropic.claude-3-haiku-20240307-v1:0"), - ], - indirect=["driver"], - ) - def test_process_output(self, driver): - assert ( - driver.process_output(json.dumps({"type": "message", "content": [{"text": "foobar"}]}).encode()).value - == "foobar" - ) - assert ( - driver.process_output( - json.dumps({"type": "content_block_delta", "delta": {"text": "foobar"}}).encode() - ).value - == "foobar" - ) diff --git a/tests/unit/drivers/prompt_models/test_bedrock_jurassic_prompt_model_driver.py b/tests/unit/drivers/prompt_models/test_bedrock_jurassic_prompt_model_driver.py deleted file mode 100644 index e0d6f1f02..000000000 --- a/tests/unit/drivers/prompt_models/test_bedrock_jurassic_prompt_model_driver.py +++ /dev/null @@ -1,71 +0,0 @@ -from unittest import mock -import json -import boto3 -import pytest -from griptape.utils import PromptStack -from griptape.drivers import AmazonBedrockPromptDriver, BedrockJurassicPromptModelDriver - - -class TestBedrockJurassicPromptModelDriver: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_tokenization = '{"prompt": {"tokens": [{}, {}, {}]}}' - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_tokenization - mock_client.invoke_model.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - return mock_session_object - - @pytest.fixture - def driver(self): - return AmazonBedrockPromptDriver( - model="ai21.j2-ultra", - session=boto3.Session(region_name="us-east-1"), - prompt_model_driver=BedrockJurassicPromptModelDriver(), - temperature=0.12345, - ).prompt_model_driver - - @pytest.fixture - def stack(self): - stack = PromptStack() - - stack.add_system_input("foo") - stack.add_user_input("bar") - - return stack - - def test_driver_stream(self): - with pytest.raises(ValueError): - AmazonBedrockPromptDriver( - model="ai21.j2-ultra", - session=boto3.Session(region_name="us-east-1"), - prompt_model_driver=BedrockJurassicPromptModelDriver(), - temperature=0.12345, - stream=True, - ).prompt_model_driver - - def test_init(self, driver): - assert driver.prompt_driver is not None - - def test_prompt_stack_to_model_input(self, driver, stack): - model_input = driver.prompt_stack_to_model_input(stack) - - assert isinstance(model_input, dict) - assert model_input["prompt"].startswith("System: foo\nUser: bar\nAssistant:") - - def test_prompt_stack_to_model_params(self, driver, stack): - assert driver.prompt_stack_to_model_params(stack)["maxTokens"] == 2042 - assert driver.prompt_stack_to_model_params(stack)["temperature"] == 0.12345 - - def test_process_output(self, driver): - assert ( - driver.process_output(json.dumps({"completions": [{"data": {"text": "foobar"}}]}).encode()).value - == "foobar" - ) diff --git a/tests/unit/drivers/prompt_models/test_bedrock_llama_prompt_model_driver.py b/tests/unit/drivers/prompt_models/test_bedrock_llama_prompt_model_driver.py deleted file mode 100644 index 8cb4b2c94..000000000 --- a/tests/unit/drivers/prompt_models/test_bedrock_llama_prompt_model_driver.py +++ /dev/null @@ -1,64 +0,0 @@ -from unittest import mock -import json -import boto3 -import pytest -from griptape.tokenizers import BedrockLlamaTokenizer -from griptape.utils import PromptStack -from griptape.drivers import AmazonBedrockPromptDriver, BedrockLlamaPromptModelDriver - - -class TestBedrockLlamaPromptModelDriver: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_tokenization = '{"generation_token_count": 13}' - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_tokenization - mock_client.invoke_model.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - return mock_session_object - - @pytest.fixture - def driver(self): - return AmazonBedrockPromptDriver( - model="meta.llama", - session=boto3.Session(region_name="us-east-1"), - prompt_model_driver=BedrockLlamaPromptModelDriver(), - temperature=0.12345, - ).prompt_model_driver - - @pytest.fixture - def stack(self): - stack = PromptStack() - - stack.add_system_input("{{ system_prompt }}") - stack.add_user_input("{{ usr_msg_1 }}") - stack.add_assistant_input("{{ model_msg_1 }}") - stack.add_user_input("{{ usr_msg_2 }}") - - return stack - - def test_init(self, driver): - assert driver.prompt_driver is not None - - def test_prompt_stack_to_model_input(self, driver, stack): - model_input = driver.prompt_stack_to_model_input(stack) - - assert isinstance(model_input, str) - assert ( - model_input - == "[INST] <>\n{{ system_prompt }}\n<>\n\n{{ usr_msg_1 }} [/INST] {{ model_msg_1 }} [INST] {{ usr_msg_2 }} [/INST]" - ) - - def test_prompt_stack_to_model_params(self, driver, stack): - assert driver.prompt_stack_to_model_params(stack)["max_gen_len"] == 2026 - assert driver.prompt_stack_to_model_params(stack)["temperature"] == 0.12345 - - def test_process_output(self, driver): - assert driver.process_output(json.dumps({"generation": "foobar"})).value == "foobar" diff --git a/tests/unit/drivers/prompt_models/test_bedrock_titan_prompt_model_driver.py b/tests/unit/drivers/prompt_models/test_bedrock_titan_prompt_model_driver.py deleted file mode 100644 index ae6d436b5..000000000 --- a/tests/unit/drivers/prompt_models/test_bedrock_titan_prompt_model_driver.py +++ /dev/null @@ -1,58 +0,0 @@ -from unittest import mock -import json -import boto3 -import pytest -from griptape.utils import PromptStack -from griptape.drivers import AmazonBedrockPromptDriver, BedrockTitanPromptModelDriver - - -class TestBedrockTitanPromptModelDriver: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_tokenization = '{"inputTextTokenCount": 13}' - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_tokenization - mock_client.invoke_model.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - return mock_session_object - - @pytest.fixture - def driver(self): - return AmazonBedrockPromptDriver( - model="amazon.titan", - session=boto3.Session(region_name="us-east-1"), - prompt_model_driver=BedrockTitanPromptModelDriver(), - temperature=0.12345, - ).prompt_model_driver - - @pytest.fixture - def stack(self): - stack = PromptStack() - - stack.add_system_input("foo") - stack.add_user_input("bar") - - return stack - - def test_init(self, driver): - assert driver.prompt_driver is not None - - def test_prompt_stack_to_model_input(self, driver, stack): - model_input = driver.prompt_stack_to_model_input(stack) - - assert isinstance(model_input, dict) - assert model_input["inputText"].startswith("Instructions: foo\n\nUser: bar\n\nBot:") - - def test_prompt_stack_to_model_params(self, driver, stack): - assert driver.prompt_stack_to_model_params(stack)["textGenerationConfig"]["maxTokenCount"] == 7994 - assert driver.prompt_stack_to_model_params(stack)["textGenerationConfig"]["temperature"] == 0.12345 - - def test_process_output(self, driver): - assert driver.process_output(json.dumps({"results": [{"outputText": "foobar"}]})).value == "foobar" diff --git a/tests/unit/drivers/prompt_models/test_sagemaker_falcon_prompt_model_driver.py b/tests/unit/drivers/prompt_models/test_sagemaker_falcon_prompt_model_driver.py deleted file mode 100644 index 78d990229..000000000 --- a/tests/unit/drivers/prompt_models/test_sagemaker_falcon_prompt_model_driver.py +++ /dev/null @@ -1,43 +0,0 @@ -import boto3 -import pytest -from griptape.utils import PromptStack -from griptape.drivers import AmazonSageMakerPromptDriver, SageMakerFalconPromptModelDriver - - -class TestSageMakerFalconPromptModelDriver: - @pytest.fixture - def driver(self): - return AmazonSageMakerPromptDriver( - endpoint="endpoint-name", - session=boto3.Session(region_name="us-east-1"), - prompt_model_driver=SageMakerFalconPromptModelDriver(), - temperature=0.12345, - ).prompt_model_driver - - @pytest.fixture - def stack(self): - stack = PromptStack() - - stack.add_system_input("foo") - stack.add_user_input("bar") - - return stack - - def test_init(self, driver): - assert driver.prompt_driver is not None - - def test_prompt_stack_to_model_input(self, driver, stack): - model_input = driver.prompt_stack_to_model_input(stack) - - assert isinstance(model_input, str) - assert model_input.startswith("foo\n\nUser: bar") - - def test_prompt_stack_to_model_params(self, driver, stack): - assert driver.prompt_stack_to_model_params(stack)["max_new_tokens"] == 590 - assert driver.prompt_stack_to_model_params(stack)["temperature"] == 0.12345 - - def test_process_output(self, driver, stack): - assert driver.process_output([{"generated_text": "foobar"}]).value == "foobar" - - def test_tokenizer_max_model_length(self, driver): - assert driver.tokenizer.tokenizer.model_max_length == 2048 diff --git a/tests/unit/drivers/prompt_models/test_sagemaker_llama_prompt_model_driver.py b/tests/unit/drivers/prompt_models/test_sagemaker_llama_prompt_model_driver.py deleted file mode 100644 index b39ce458e..000000000 --- a/tests/unit/drivers/prompt_models/test_sagemaker_llama_prompt_model_driver.py +++ /dev/null @@ -1,67 +0,0 @@ -import boto3 -import pytest -from griptape.utils import PromptStack -from griptape.drivers import AmazonSageMakerPromptDriver, SageMakerLlamaPromptModelDriver - - -class TestSageMakerLlamaPromptModelDriver: - @pytest.fixture(autouse=True) - def llama3_instruct_tokenizer(self, mocker): - tokenizer = mocker.patch("transformers.AutoTokenizer").return_value - tokenizer.model_max_length = 8000 - - return tokenizer - - @pytest.fixture(autouse=True) - def hugging_face_tokenizer(self, mocker, llama3_instruct_tokenizer): - tokenizer = mocker.patch( - "griptape.drivers.prompt_model.sagemaker_llama_prompt_model_driver.HuggingFaceTokenizer" - ).return_value - tokenizer.count_output_tokens_left.return_value = 7991 - tokenizer.tokenizer = llama3_instruct_tokenizer - return tokenizer - - @pytest.fixture - def driver(self): - return AmazonSageMakerPromptDriver( - endpoint="endpoint-name", - model="inference-component-name", - session=boto3.Session(region_name="us-east-1"), - prompt_model_driver=SageMakerLlamaPromptModelDriver(), - temperature=0.12345, - ).prompt_model_driver - - @pytest.fixture - def stack(self): - stack = PromptStack() - - stack.add_system_input("foo") - stack.add_user_input("bar") - - return stack - - def test_init(self, driver): - assert driver.prompt_driver is not None - - def test_prompt_stack_to_model_input(self, driver, stack, hugging_face_tokenizer): - driver.prompt_stack_to_model_input(stack) - - hugging_face_tokenizer.tokenizer.apply_chat_template.assert_called_once_with( - [{"role": "system", "content": "foo"}, {"role": "user", "content": "bar"}], - tokenize=False, - add_generation_prompt=True, - ) - - def test_prompt_stack_to_model_params(self, driver, stack): - assert driver.prompt_stack_to_model_params(stack)["max_new_tokens"] == 7991 - assert driver.prompt_stack_to_model_params(stack)["temperature"] == 0.12345 - - def test_process_output(self, driver, stack): - assert driver.process_output({"generated_text": "foobar"}).value == "foobar" - - def test_process_output_invalid_format(self, driver, stack): - with pytest.raises(ValueError): - assert driver.process_output([{"generated_text": "foobar"}]) - - def test_tokenizer_max_model_length(self, driver): - assert driver.tokenizer.tokenizer.model_max_length == 8000 diff --git a/tests/unit/drivers/structure_run/test_local_structure_run_driver.py b/tests/unit/drivers/structure_run/test_local_structure_run_driver.py index 921a4b013..cb7b3058e 100644 --- a/tests/unit/drivers/structure_run/test_local_structure_run_driver.py +++ b/tests/unit/drivers/structure_run/test_local_structure_run_driver.py @@ -22,7 +22,7 @@ def test_run(self): def test_run_with_env(self): pipeline = Pipeline() - agent = Agent(prompt_driver=MockPromptDriver(mock_output=lambda: os.environ["key"])) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=lambda _: os.environ["key"])) driver = LocalStructureRunDriver(structure_factory_fn=lambda: agent, env={"key": "value"}) task = StructureRunTask(driver=driver) diff --git a/tests/unit/engines/summary/test_prompt_summary_engine.py b/tests/unit/engines/summary/test_prompt_summary_engine.py index 52179bdfb..59b36f48e 100644 --- a/tests/unit/engines/summary/test_prompt_summary_engine.py +++ b/tests/unit/engines/summary/test_prompt_summary_engine.py @@ -1,7 +1,9 @@ import pytest from griptape.artifacts import TextArtifact, ListArtifact from griptape.engines import PromptSummaryEngine +from griptape.utils import PromptStack from tests.mocks.mock_prompt_driver import MockPromptDriver +import os class TestPromptSummaryEngine: @@ -16,3 +18,25 @@ def test_summarize_artifacts(self, engine): assert ( engine.summarize_artifacts(ListArtifact([TextArtifact("foo"), TextArtifact("bar")])).value == "mock output" ) + + def test_max_token_multiplier_invalid(self, engine): + with pytest.raises(ValueError): + PromptSummaryEngine(prompt_driver=MockPromptDriver(), max_token_multiplier=0) + + with pytest.raises(ValueError): + PromptSummaryEngine(prompt_driver=MockPromptDriver(), max_token_multiplier=10000) + + def test_chunked_summary(self, engine): + def smaller_input(prompt_stack: PromptStack): + return prompt_stack.inputs[0].content[: (len(prompt_stack.inputs[0].content) // 2)] + + engine = PromptSummaryEngine(prompt_driver=MockPromptDriver(mock_output="smaller_input")) + + def copy_test_resource(resource_path: str): + file_dir = os.path.dirname(__file__) + full_path = os.path.join(file_dir, "../../../resources", resource_path) + full_path = os.path.normpath(full_path) + with open(full_path) as f: + return f.read() + + assert engine.summarize_text(copy_test_resource("test.txt") * 50) diff --git a/tests/unit/loaders/test_web_loader.py b/tests/unit/loaders/test_web_loader.py index fb63e87eb..e26573539 100644 --- a/tests/unit/loaders/test_web_loader.py +++ b/tests/unit/loaders/test_web_loader.py @@ -1,4 +1,5 @@ import pytest +from griptape.artifacts.error_artifact import ErrorArtifact from griptape.loaders import WebLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -22,6 +23,14 @@ def test_load(self, loader): assert artifacts[0].embedding == [0, 1] + def test_load_exception(self, mocker, loader): + mocker.patch("trafilatura.fetch_url", side_effect=Exception("error")) + source = "https://github.com/griptape-ai/griptape" + artifact = loader.load(source) + + assert isinstance(artifact, ErrorArtifact) + assert f"Error loading from source: {source}" == artifact.value + def test_load_collection(self, loader): artifacts = loader.load_collection( ["https://github.com/griptape-ai/griptape", "https://github.com/griptape-ai/griptape-docs"] @@ -38,11 +47,13 @@ def test_load_collection(self, loader): def test_empty_page_string_response(self, loader, mocker): mocker.patch("trafilatura.extract", return_value="") - with pytest.raises(Exception, match="can't extract page"): - loader.load("https://example.com/") + artifact = loader.load("https://example.com/") + assert isinstance(artifact, ErrorArtifact) + assert str(artifact.exception) == "can't extract page" def test_empty_page_none_response(self, loader, mocker): mocker.patch("trafilatura.extract", return_value=None) - with pytest.raises(Exception, match="can't extract page"): - loader.load("https://example.com/") + artifact = loader.load("https://example.com/") + assert isinstance(artifact, ErrorArtifact) + assert str(artifact.exception) == "can't extract page" diff --git a/tests/unit/memory/structure/test_conversation_memory.py b/tests/unit/memory/structure/test_conversation_memory.py index 665dca9b2..298e5ac3f 100644 --- a/tests/unit/memory/structure/test_conversation_memory.py +++ b/tests/unit/memory/structure/test_conversation_memory.py @@ -1,7 +1,10 @@ import json +from griptape.structures import Agent +from griptape.utils import PromptStack from griptape.memory.structure import ConversationMemory, Run, BaseConversationMemory from griptape.structures import Pipeline from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.mocks.mock_tokenizer import MockTokenizer from griptape.tasks import PromptTask @@ -69,3 +72,97 @@ def test_buffering(self): assert len(pipeline.conversation_memory.runs) == 2 assert pipeline.conversation_memory.runs[0].input == "run4" assert pipeline.conversation_memory.runs[1].input == "run5" + + def test_add_to_prompt_stack_autopruing_disabled(self): + agent = Agent(prompt_driver=MockPromptDriver()) + memory = ConversationMemory( + autoprune=False, + runs=[ + Run(input="foo1", output="bar1"), + Run(input="foo2", output="bar2"), + Run(input="foo3", output="bar3"), + Run(input="foo4", output="bar4"), + Run(input="foo5", output="bar5"), + ], + ) + memory.structure = agent + prompt_stack = PromptStack() + prompt_stack.add_user_input("foo") + prompt_stack.add_assistant_input("bar") + memory.add_to_prompt_stack(prompt_stack) + + assert len(prompt_stack.inputs) == 12 + + def test_add_to_prompt_stack_autopruning_enabled(self): + # All memory is pruned. + agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=0))) + memory = ConversationMemory( + autoprune=True, + runs=[ + Run(input="foo1", output="bar1"), + Run(input="foo2", output="bar2"), + Run(input="foo3", output="bar3"), + Run(input="foo4", output="bar4"), + Run(input="foo5", output="bar5"), + ], + ) + memory.structure = agent + prompt_stack = PromptStack() + prompt_stack.add_system_input("fizz") + prompt_stack.add_user_input("foo") + prompt_stack.add_assistant_input("bar") + memory.add_to_prompt_stack(prompt_stack) + + assert len(prompt_stack.inputs) == 3 + + # No memory is pruned. + agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=1000))) + memory = ConversationMemory( + autoprune=True, + runs=[ + Run(input="foo1", output="bar1"), + Run(input="foo2", output="bar2"), + Run(input="foo3", output="bar3"), + Run(input="foo4", output="bar4"), + Run(input="foo5", output="bar5"), + ], + ) + memory.structure = agent + prompt_stack = PromptStack() + prompt_stack.add_system_input("fizz") + prompt_stack.add_user_input("foo") + prompt_stack.add_assistant_input("bar") + memory.add_to_prompt_stack(prompt_stack) + + assert len(prompt_stack.inputs) == 13 + + # One memory is pruned. + # MockTokenizer's max_input_tokens set to one below the sum of memory + system prompt tokens + # so that a single memory is pruned. + agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=160))) + memory = ConversationMemory( + autoprune=True, + runs=[ + # All of these sum to 155 tokens with the MockTokenizer. + Run(input="foo1", output="bar1"), + Run(input="foo2", output="bar2"), + Run(input="foo3", output="bar3"), + Run(input="foo4", output="bar4"), + Run(input="foo5", output="bar5"), + ], + ) + memory.structure = agent + prompt_stack = PromptStack() + # And then another 6 tokens from fizz for a total of 161 tokens. + prompt_stack.add_system_input("fizz") + prompt_stack.add_user_input("foo") + prompt_stack.add_assistant_input("bar") + memory.add_to_prompt_stack(prompt_stack, 1) + + # We expect one run (2 prompt stack inputs) to be pruned. + assert len(prompt_stack.inputs) == 11 + assert prompt_stack.inputs[0].content == "fizz" + assert prompt_stack.inputs[1].content == "foo2" + assert prompt_stack.inputs[2].content == "bar2" + assert prompt_stack.inputs[-2].content == "foo" + assert prompt_stack.inputs[-1].content == "bar" diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index 371aee8a8..e6c2a1f01 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -252,3 +252,13 @@ def test_deprecation(self): with pytest.deprecated_call(): Agent(stream=True) + + def finished_tasks(self): + task = PromptTask("test prompt") + agent = Agent(prompt_driver=MockPromptDriver()) + + agent.add_task(task) + + agent.run("hello") + + assert len(agent.finished_tasks) == 1 diff --git a/tests/unit/structures/test_workflow.py b/tests/unit/structures/test_workflow.py index 970d43e74..bbcf5138e 100644 --- a/tests/unit/structures/test_workflow.py +++ b/tests/unit/structures/test_workflow.py @@ -1,16 +1,34 @@ +import time import pytest +from pytest import fixture from griptape.memory.task.storage import TextArtifactStorage from tests.mocks.mock_prompt_driver import MockPromptDriver from griptape.rules import Rule, Ruleset -from griptape.tasks import PromptTask, BaseTask, ToolkitTask +from griptape.tasks import PromptTask, BaseTask, ToolkitTask, CodeExecutionTask from griptape.structures import Workflow +from griptape.artifacts import ErrorArtifact, TextArtifact from griptape.memory.structure import ConversationMemory from tests.mocks.mock_tool.tool import MockTool from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestWorkflow: + @fixture + def waiting_task(self): + def fn(task): + time.sleep(10) + return TextArtifact("done") + + return CodeExecutionTask(run_fn=fn) + + @fixture + def error_artifact_task(self): + def fn(task): + return ErrorArtifact("error") + + return CodeExecutionTask(run_fn=fn) + def test_init(self): driver = MockPromptDriver() workflow = Workflow(prompt_driver=driver, rulesets=[Ruleset("TestRuleset", [Rule("test")])]) @@ -140,10 +158,10 @@ def test_tasks_initialization(self): assert workflow.tasks[1].id == "test2" assert workflow.tasks[2].id == "test3" assert len(first_task.parents) == 0 - assert len(first_task.children) == 1 - assert len(second_task.parents) == 1 - assert len(second_task.children) == 1 - assert len(third_task.parents) == 1 + assert len(first_task.children) == 0 + assert len(second_task.parents) == 0 + assert len(second_task.children) == 0 + assert len(third_task.parents) == 0 assert len(third_task.children) == 0 def test_add_task(self): @@ -161,8 +179,8 @@ def test_add_task(self): assert first_task.structure == workflow assert second_task.structure == workflow assert len(first_task.parents) == 0 - assert len(first_task.children) == 1 - assert len(second_task.parents) == 1 + assert len(first_task.children) == 0 + assert len(second_task.parents) == 0 assert len(second_task.children) == 0 def test_add_tasks(self): @@ -179,8 +197,8 @@ def test_add_tasks(self): assert first_task.structure == workflow assert second_task.structure == workflow assert len(first_task.parents) == 0 - assert len(first_task.children) == 1 - assert len(second_task.parents) == 1 + assert len(first_task.children) == 0 + assert len(second_task.parents) == 0 assert len(second_task.children) == 0 def test_run(self): @@ -210,7 +228,111 @@ def test_run_with_args(self): assert task.input.to_text() == "-" - def test_run_topology_1(self): + @pytest.mark.parametrize( + "tasks", + [ + [PromptTask(id="task1", parent_ids=["missing"])], + [PromptTask(id="task1", child_ids=["missing"])], + [PromptTask(id="task1"), PromptTask(id="task2", parent_ids=["missing"])], + [PromptTask(id="task1"), PromptTask(id="task2", parent_ids=["task1", "missing"])], + [PromptTask(id="task1"), PromptTask(id="task2", parent_ids=["task1"], child_ids=["missing"])], + ], + ) + def test_run_raises_on_missing_parent_or_child_id(self, tasks): + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=tasks) + + with pytest.raises(ValueError) as e: + workflow.run() + + assert e.value.args[0] == "Task with id missing doesn't exist." + + def test_run_topology_1_declarative_parents(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1"), + PromptTask("test2", id="task2", parent_ids=["task1"]), + PromptTask("test3", id="task3", parent_ids=["task1"]), + PromptTask("test4", id="task4", parent_ids=["task2", "task3"]), + ], + ) + + workflow.run() + + self._validate_topology_1(workflow) + + def test_run_topology_1_declarative_children(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1", child_ids=["task2", "task3"]), + PromptTask("test2", id="task2", child_ids=["task4"]), + PromptTask("test3", id="task3", child_ids=["task4"]), + PromptTask("test4", id="task4"), + ], + ) + + workflow.run() + + self._validate_topology_1(workflow) + + def test_run_topology_1_declarative_mixed(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1", child_ids=["task3"]), + PromptTask("test2", id="task2", parent_ids=["task1"], child_ids=["task4"]), + PromptTask("test3", id="task3"), + PromptTask("test4", id="task4", parent_ids=["task2", "task3"]), + ], + ) + + workflow.run() + + self._validate_topology_1(workflow) + + def test_run_topology_1_imperative_parents(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + task2.add_parent(task1) + task3.add_parent("task1") + task4.add_parents([task2, "task3"]) + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[task1, task2, task3, task4]) + + workflow.run() + + self._validate_topology_1(workflow) + + def test_run_topology_1_imperative_children(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + task1.add_children([task2, task3]) + task2.add_child(task4) + task3.add_child(task4) + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[task1, task2, task3, task4]) + + workflow.run() + + self._validate_topology_1(workflow) + + def test_run_topology_1_imperative_mixed(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + task1.add_children([task2, task3]) + task4.add_parents([task2, task3]) + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[task1, task2, task3, task4]) + + workflow.run() + + self._validate_topology_1(workflow) + + def test_run_topology_1_imperative_insert(self): task1 = PromptTask("test1", id="task1") task2 = PromptTask("test2", id="task2") task3 = PromptTask("test3", id="task3") @@ -225,60 +347,152 @@ def test_run_topology_1(self): workflow.run() - assert task1.state == BaseTask.State.FINISHED - assert task1.parent_ids == [] - assert task1.child_ids == ["task2", "task3"] + self._validate_topology_1(workflow) + + def test_run_topology_2_declarative_parents(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("testa", id="taska"), + PromptTask("testb", id="taskb", parent_ids=["taska"]), + PromptTask("testc", id="taskc", parent_ids=["taska"]), + PromptTask("testd", id="taskd", parent_ids=["taska", "taskb", "taskc"]), + PromptTask("teste", id="taske", parent_ids=["taska", "taskd", "taskc"]), + ], + ) - assert task2.state == BaseTask.State.FINISHED - assert task2.parent_ids == ["task1"] - assert task2.child_ids == ["task4"] + workflow.run() - assert task3.state == BaseTask.State.FINISHED - assert task3.parent_ids == ["task1"] - assert task3.child_ids == ["task4"] + self._validate_topology_2(workflow) + + def test_run_topology_2_declarative_children(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("testa", id="taska", child_ids=["taskb", "taskc", "taskd", "taske"]), + PromptTask("testb", id="taskb", child_ids=["taskd"]), + PromptTask("testc", id="taskc", child_ids=["taskd", "taske"]), + PromptTask("testd", id="taskd", child_ids=["taske"]), + PromptTask("teste", id="taske", child_ids=[]), + ], + ) - assert task4.state == BaseTask.State.FINISHED - assert task4.parent_ids == ["task2", "task3"] - assert task4.child_ids == [] + workflow.run() - def test_run_topology_2(self): - """Adapted from https://en.wikipedia.org/wiki/Directed_acyclic_graph#/media/File:Tred-G.svg""" + self._validate_topology_2(workflow) + + def test_run_topology_2_imperative_parents(self): taska = PromptTask("testa", id="taska") taskb = PromptTask("testb", id="taskb") taskc = PromptTask("testc", id="taskc") taskd = PromptTask("testd", id="taskd") taske = PromptTask("teste", id="taske") - workflow = Workflow(prompt_driver=MockPromptDriver()) + taskb.add_parent(taska) + taskc.add_parent("taska") + taskd.add_parents([taska, taskb, taskc]) + taske.add_parents(["taska", taskd, "taskc"]) + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[taska, taskb, taskc, taskd, taske]) + + workflow.run() + + self._validate_topology_2(workflow) + + def test_run_topology_2_imperative_children(self): + taska = PromptTask("testa", id="taska") + taskb = PromptTask("testb", id="taskb") + taskc = PromptTask("testc", id="taskc") + taskd = PromptTask("testd", id="taskd") + taske = PromptTask("teste", id="taske") + taska.add_children([taskb, taskc, taskd, taske]) + taskb.add_child(taskd) + taskc.add_children([taskd, taske]) + taskd.add_child(taske) + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[taska, taskb, taskc, taskd, taske]) + + workflow.run() + + self._validate_topology_2(workflow) + + def test_run_topology_2_imperative_mixed(self): + taska = PromptTask("testa", id="taska") + taskb = PromptTask("testb", id="taskb") + taskc = PromptTask("testc", id="taskc") + taskd = PromptTask("testd", id="taskd") + taske = PromptTask("teste", id="taske") + taska.add_children([taskb, taskc, taskd, taske]) + taskb.add_child(taskd) + taskd.add_parent(taskc) + taske.add_parents(["taska", taskd, "taskc"]) + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[taska, taskb, taskc, taskd, taske]) + + workflow.run() + + self._validate_topology_2(workflow) + def test_run_topology_2_imperative_insert(self): + taska = PromptTask("testa", id="taska") + taskb = PromptTask("testb", id="taskb") + taskc = PromptTask("testc", id="taskc") + taskd = PromptTask("testd", id="taskd") + taske = PromptTask("teste", id="taske") + workflow = Workflow(prompt_driver=MockPromptDriver()) workflow.add_task(taska) workflow.add_task(taske) + taske.add_parent(taska) workflow.insert_tasks(taska, taskd, taske, preserve_relationship=True) workflow.insert_tasks(taska, [taskc], [taskd, taske], preserve_relationship=True) workflow.insert_tasks(taska, taskb, taskd, preserve_relationship=True) workflow.run() - assert taska.state == BaseTask.State.FINISHED - assert taska.parent_ids == [] - assert set(taska.child_ids) == {"taskb", "taskd", "taskc", "taske"} + self._validate_topology_2(workflow) + + def test_run_topology_3_declarative_parents(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1"), + PromptTask("test2", id="task2", parent_ids=["task4"]), + PromptTask("test4", id="task4", parent_ids=["task1"]), + PromptTask("test3", id="task3", parent_ids=["task2"]), + ], + ) - assert taskb.state == BaseTask.State.FINISHED - assert taskb.parent_ids == ["taska"] - assert taskb.child_ids == ["taskd"] + workflow.run() - assert taskc.state == BaseTask.State.FINISHED - assert taskc.parent_ids == ["taska"] - assert set(taskc.child_ids) == {"taskd", "taske"} + self._validate_topology_3(workflow) + + def test_run_topology_3_declarative_children(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1", child_ids=["task4"]), + PromptTask("test2", id="task2", child_ids=["task3"]), + PromptTask("test4", id="task4", child_ids=["task2"]), + PromptTask("test3", id="task3", child_ids=[]), + ], + ) - assert taskd.state == BaseTask.State.FINISHED - assert set(taskd.parent_ids) == {"taskb", "taska", "taskc"} - assert taskd.child_ids == ["taske"] + workflow.run() - assert taske.state == BaseTask.State.FINISHED - assert set(taske.parent_ids) == {"taskd", "taskc", "taska"} - assert taske.child_ids == [] + self._validate_topology_3(workflow) + + def test_run_topology_3_declarative_mixed(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1"), + PromptTask("test2", id="task2", parent_ids=["task4"], child_ids=["task3"]), + PromptTask("test4", id="task4", parent_ids=["task1"], child_ids=["task2"]), + PromptTask("test3", id="task3"), + ], + ) - def test_run_topology_3(self): + workflow.run() + + self._validate_topology_3(workflow) + + def test_run_topology_3_imperative_insert(self): task1 = PromptTask("test1", id="task1") task2 = PromptTask("test2", id="task2") task3 = PromptTask("test3", id="task3") @@ -288,28 +502,75 @@ def test_run_topology_3(self): workflow + task1 workflow + task2 workflow + task3 + task2.add_parent(task1) + task3.add_parent(task2) workflow.insert_tasks(task1, task4, task2) workflow.run() - assert task1.state == BaseTask.State.FINISHED - assert task1.parent_ids == [] - assert task1.child_ids == ["task4"] + self._validate_topology_3(workflow) + + def test_run_topology_4_declarative_parents(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask(id="collect_movie_info"), + PromptTask(id="movie_info_1", parent_ids=["collect_movie_info"]), + PromptTask(id="movie_info_2", parent_ids=["collect_movie_info"]), + PromptTask(id="movie_info_3", parent_ids=["collect_movie_info"]), + PromptTask(id="compare_movies", parent_ids=["movie_info_1", "movie_info_2", "movie_info_3"]), + PromptTask(id="send_email_task", parent_ids=["compare_movies"]), + PromptTask(id="save_to_disk", parent_ids=["compare_movies"]), + PromptTask(id="publish_website", parent_ids=["compare_movies"]), + PromptTask(id="summarize_to_slack", parent_ids=["send_email_task", "save_to_disk", "publish_website"]), + ], + ) - assert task2.state == BaseTask.State.FINISHED - assert task2.parent_ids == ["task4"] - assert task2.child_ids == ["task3"] + workflow.run() - assert task3.state == BaseTask.State.FINISHED - assert task3.parent_ids == ["task2"] - assert task3.child_ids == [] + self._validate_topology_4(workflow) + + def test_run_topology_4_declarative_children(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask(id="collect_movie_info", child_ids=["movie_info_1", "movie_info_2", "movie_info_3"]), + PromptTask(id="movie_info_1", child_ids=["compare_movies"]), + PromptTask(id="movie_info_2", child_ids=["compare_movies"]), + PromptTask(id="movie_info_3", child_ids=["compare_movies"]), + PromptTask(id="compare_movies", child_ids=["send_email_task", "save_to_disk", "publish_website"]), + PromptTask(id="send_email_task", child_ids=["summarize_to_slack"]), + PromptTask(id="save_to_disk", child_ids=["summarize_to_slack"]), + PromptTask(id="publish_website", child_ids=["summarize_to_slack"]), + PromptTask(id="summarize_to_slack", child_ids=[]), + ], + ) - assert task4.state == BaseTask.State.FINISHED - assert task4.parent_ids == ["task1"] - assert task4.child_ids == ["task2"] + workflow.run() - def test_run_topology_4(self): - workflow = Workflow(prompt_driver=MockPromptDriver()) + self._validate_topology_4(workflow) + + def test_run_topology_4_declarative_mixed(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask(id="collect_movie_info"), + PromptTask(id="movie_info_1", parent_ids=["collect_movie_info"], child_ids=["compare_movies"]), + PromptTask(id="movie_info_2", parent_ids=["collect_movie_info"], child_ids=["compare_movies"]), + PromptTask(id="movie_info_3", parent_ids=["collect_movie_info"], child_ids=["compare_movies"]), + PromptTask(id="compare_movies"), + PromptTask(id="send_email_task", parent_ids=["compare_movies"], child_ids=["summarize_to_slack"]), + PromptTask(id="save_to_disk", parent_ids=["compare_movies"], child_ids=["summarize_to_slack"]), + PromptTask(id="publish_website", parent_ids=["compare_movies"], child_ids=["summarize_to_slack"]), + PromptTask(id="summarize_to_slack"), + ], + ) + + workflow.run() + + self._validate_topology_4(workflow) + + def test_run_topology_4_imperative_insert(self): collect_movie_info = PromptTask(id="collect_movie_info") summarize_to_slack = PromptTask(id="summarize_to_slack") movie_info_1 = PromptTask(id="movie_info_1") @@ -321,30 +582,34 @@ def test_run_topology_4(self): publish_website = PromptTask(id="publish_website") movie_info_3 = PromptTask(id="movie_info_3") + workflow = Workflow(prompt_driver=MockPromptDriver()) workflow.add_tasks(collect_movie_info, summarize_to_slack) workflow.insert_tasks(collect_movie_info, [movie_info_1, movie_info_2, movie_info_3], summarize_to_slack) workflow.insert_tasks([movie_info_1, movie_info_2, movie_info_3], compare_movies, summarize_to_slack) workflow.insert_tasks(compare_movies, [send_email_task, save_to_disk, publish_website], summarize_to_slack) - assert set(collect_movie_info.child_ids) == {"movie_info_1", "movie_info_2", "movie_info_3"} - - assert set(movie_info_1.parent_ids) == {"collect_movie_info"} - assert set(movie_info_2.parent_ids) == {"collect_movie_info"} - assert set(movie_info_3.parent_ids) == {"collect_movie_info"} - assert set(movie_info_1.child_ids) == {"compare_movies"} - assert set(movie_info_2.child_ids) == {"compare_movies"} - assert set(movie_info_3.child_ids) == {"compare_movies"} - - assert set(compare_movies.parent_ids) == {"movie_info_1", "movie_info_2", "movie_info_3"} - assert set(compare_movies.child_ids) == {"send_email_task", "save_to_disk", "publish_website"} - - assert set(send_email_task.parent_ids) == {"compare_movies"} - assert set(save_to_disk.parent_ids) == {"compare_movies"} - assert set(publish_website.parent_ids) == {"compare_movies"} - - assert set(send_email_task.child_ids) == {"summarize_to_slack"} - assert set(save_to_disk.child_ids) == {"summarize_to_slack"} - assert set(publish_website.child_ids) == {"summarize_to_slack"} + self._validate_topology_4(workflow) + + @pytest.mark.parametrize( + "tasks", + [ + [PromptTask(id="a", parent_ids=["a"])], + [PromptTask(id="a"), PromptTask(id="b", parent_ids=["a", "b"])], + [PromptTask(id="a", parent_ids=["b"]), PromptTask(id="b", parent_ids=["a"])], + [ + PromptTask(id="a", parent_ids=["c"]), + PromptTask(id="b", parent_ids=["a"]), + PromptTask(id="c", parent_ids=["b"]), + ], + ], + ) + def test_run_raises_on_cycle(self, tasks): + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=tasks) + + with pytest.raises(ValueError) as e: + workflow.run() + + assert e.value.args[0] == "nodes are in a cycle" def test_input_task(self): task1 = PromptTask("prompt1") @@ -372,6 +637,15 @@ def test_output_task(self): assert task4 == workflow.output_task + task4.add_parents([task2, task3]) + task1.add_children([task2, task3]) + + # task4 is the final task, but its defined at index 0 + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[task4, task1, task2, task3]) + + # ouput_task topologically should be task4 + assert task4 == workflow.output_task + def test_to_graph(self): task1 = PromptTask("prompt1", id="task1") task2 = PromptTask("prompt2", id="task2") @@ -417,6 +691,9 @@ def test_context(self): workflow + task workflow + child + task.add_parent(parent) + task.add_child(child) + context = workflow.context(task) assert context["parent_outputs"] == {parent.id: ""} @@ -426,6 +703,7 @@ def test_context(self): context = workflow.context(task) assert context["parent_outputs"] == {parent.id: parent.output.to_text()} + assert context["parents_output_text"] == "mock output" assert context["structure"] == workflow assert context["parents"] == {parent.id: parent} assert context["children"] == {child.id: child} @@ -439,3 +717,141 @@ def test_deprecation(self): with pytest.deprecated_call(): Workflow(stream=True) + + def test_run_with_error_artifact(self, error_artifact_task, waiting_task): + end_task = PromptTask("end") + end_task.add_parents([error_artifact_task, waiting_task]) + workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[waiting_task, error_artifact_task, end_task]) + workflow.run() + + assert workflow.output is None + + @staticmethod + def _validate_topology_1(workflow): + assert len(workflow.tasks) == 4 + assert workflow.input_task.id == "task1" + assert workflow.output_task.id == "task4" + assert workflow.input_task.id == workflow.tasks[0].id + assert workflow.output_task.id == workflow.tasks[-1].id + + task1 = workflow.find_task("task1") + assert task1.state == BaseTask.State.FINISHED + assert task1.parent_ids == [] + assert sorted(task1.child_ids) == ["task2", "task3"] + + task2 = workflow.find_task("task2") + assert task2.state == BaseTask.State.FINISHED + assert task2.parent_ids == ["task1"] + assert task2.child_ids == ["task4"] + + task3 = workflow.find_task("task3") + assert task3.state == BaseTask.State.FINISHED + assert task3.parent_ids == ["task1"] + assert task3.child_ids == ["task4"] + + task4 = workflow.find_task("task4") + assert task4.state == BaseTask.State.FINISHED + assert sorted(task4.parent_ids) == ["task2", "task3"] + assert task4.child_ids == [] + + @staticmethod + def _validate_topology_2(workflow): + """Adapted from https://en.wikipedia.org/wiki/Directed_acyclic_graph#/media/File:Tred-G.svg""" + assert len(workflow.tasks) == 5 + assert workflow.input_task.id == "taska" + assert workflow.output_task.id == "taske" + assert workflow.input_task.id == workflow.tasks[0].id + assert workflow.output_task.id == workflow.tasks[-1].id + + taska = workflow.find_task("taska") + assert taska.state == BaseTask.State.FINISHED + assert taska.parent_ids == [] + assert sorted(taska.child_ids) == ["taskb", "taskc", "taskd", "taske"] + + taskb = workflow.find_task("taskb") + assert taskb.state == BaseTask.State.FINISHED + assert taskb.parent_ids == ["taska"] + assert taskb.child_ids == ["taskd"] + + taskc = workflow.find_task("taskc") + assert taskc.state == BaseTask.State.FINISHED + assert taskc.parent_ids == ["taska"] + assert sorted(taskc.child_ids) == ["taskd", "taske"] + + taskd = workflow.find_task("taskd") + assert taskd.state == BaseTask.State.FINISHED + assert sorted(taskd.parent_ids) == ["taska", "taskb", "taskc"] + assert taskd.child_ids == ["taske"] + + taske = workflow.find_task("taske") + assert taske.state == BaseTask.State.FINISHED + assert sorted(taske.parent_ids) == ["taska", "taskc", "taskd"] + assert taske.child_ids == [] + + @staticmethod + def _validate_topology_3(workflow): + assert len(workflow.tasks) == 4 + assert workflow.input_task.id == "task1" + assert workflow.output_task.id == "task3" + assert workflow.input_task.id == workflow.tasks[0].id + assert workflow.output_task.id == workflow.tasks[-1].id + + task1 = workflow.find_task("task1") + assert task1.state == BaseTask.State.FINISHED + assert task1.parent_ids == [] + assert task1.child_ids == ["task4"] + + task2 = workflow.find_task("task2") + assert task2.state == BaseTask.State.FINISHED + assert task2.parent_ids == ["task4"] + assert task2.child_ids == ["task3"] + + task3 = workflow.find_task("task3") + assert task3.state == BaseTask.State.FINISHED + assert task3.parent_ids == ["task2"] + assert task3.child_ids == [] + + task4 = workflow.find_task("task4") + assert task4.state == BaseTask.State.FINISHED + assert task4.parent_ids == ["task1"] + assert task4.child_ids == ["task2"] + + @staticmethod + def _validate_topology_4(workflow): + assert len(workflow.tasks) == 9 + assert workflow.input_task.id == "collect_movie_info" + assert workflow.output_task.id == "summarize_to_slack" + assert workflow.input_task.id == workflow.tasks[0].id + assert workflow.output_task.id == workflow.tasks[-1].id + + collect_movie_info = workflow.find_task("collect_movie_info") + assert collect_movie_info.parent_ids == [] + assert sorted(collect_movie_info.child_ids) == ["movie_info_1", "movie_info_2", "movie_info_3"] + + movie_info_1 = workflow.find_task("movie_info_1") + assert movie_info_1.parent_ids == ["collect_movie_info"] + assert movie_info_1.child_ids == ["compare_movies"] + + movie_info_2 = workflow.find_task("movie_info_2") + assert movie_info_2.parent_ids == ["collect_movie_info"] + assert movie_info_2.child_ids == ["compare_movies"] + + movie_info_3 = workflow.find_task("movie_info_3") + assert movie_info_3.parent_ids == ["collect_movie_info"] + assert movie_info_3.child_ids == ["compare_movies"] + + compare_movies = workflow.find_task("compare_movies") + assert sorted(compare_movies.parent_ids) == ["movie_info_1", "movie_info_2", "movie_info_3"] + assert sorted(compare_movies.child_ids) == ["publish_website", "save_to_disk", "send_email_task"] + + send_email_task = workflow.find_task("send_email_task") + assert send_email_task.parent_ids == ["compare_movies"] + assert send_email_task.child_ids == ["summarize_to_slack"] + + save_to_disk = workflow.find_task("save_to_disk") + assert save_to_disk.parent_ids == ["compare_movies"] + assert save_to_disk.child_ids == ["summarize_to_slack"] + + publish_website = workflow.find_task("publish_website") + assert publish_website.parent_ids == ["compare_movies"] + assert publish_website.child_ids == ["summarize_to_slack"] diff --git a/tests/unit/tasks/test_audio_transcription_task.py b/tests/unit/tasks/test_audio_transcription_task.py index fdab5f730..3a53fd49d 100644 --- a/tests/unit/tasks/test_audio_transcription_task.py +++ b/tests/unit/tasks/test_audio_transcription_task.py @@ -2,10 +2,11 @@ import pytest -from griptape.artifacts import AudioArtifact +from griptape.artifacts import AudioArtifact, TextArtifact from griptape.engines import AudioTranscriptionEngine -from griptape.structures import Agent +from griptape.structures import Agent, Pipeline from griptape.tasks import BaseTask, AudioTranscriptionTask +from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_structure_config import MockStructureConfig @@ -36,3 +37,17 @@ def test_config_audio_transcription_engine(self, audio_artifact): Agent(config=MockStructureConfig()).add_task(task) assert isinstance(task.audio_transcription_engine, AudioTranscriptionEngine) + + def test_run(self, audio_artifact, audio_transcription_engine): + audio_transcription_engine.run.return_value = TextArtifact("mock transcription") + logger = Mock() + + task = AudioTranscriptionTask(audio_artifact, audio_transcription_engine=audio_transcription_engine) + pipeline = Pipeline(prompt_driver=MockPromptDriver(), logger=logger) + pipeline.add_task(task) + + assert pipeline.run().output.to_text() == "mock transcription" + + def test_before_run(self, audio_artifact, audio_transcription_engine): + task = AudioTranscriptionTask(audio_artifact, audio_transcription_engine=audio_transcription_engine) + task diff --git a/tests/unit/tasks/test_base_audio_input_task.py b/tests/unit/tasks/test_base_audio_input_task.py new file mode 100644 index 000000000..e11074880 --- /dev/null +++ b/tests/unit/tasks/test_base_audio_input_task.py @@ -0,0 +1,26 @@ +import pytest + +from tests.mocks.mock_audio_input_task import MockAudioInputTask +from griptape.artifacts import AudioArtifact, TextArtifact +from tests.mocks.mock_text_input_task import MockTextInputTask + + +class TestBaseAudioInputTask: + @pytest.fixture + def audio_artifact(self): + return AudioArtifact(b"audio content", format="mp3") + + def test_audio_artifact_input(self, audio_artifact): + task = MockAudioInputTask(audio_artifact) + assert task.input.value == audio_artifact.value + + audio_artifact.value = b"new audio content" + task.input = audio_artifact + assert task.input.value == audio_artifact.value + + def test_callable_input(self, audio_artifact): + assert MockTextInputTask(lambda _: audio_artifact).input.value == audio_artifact.value + + def test_bad_input(self): + with pytest.raises(ValueError): + assert MockAudioInputTask(TextArtifact("foobar")).input.value == "foobar" diff --git a/tests/unit/tasks/test_base_task.py b/tests/unit/tasks/test_base_task.py index 3048b7d7a..7fe2810f5 100644 --- a/tests/unit/tasks/test_base_task.py +++ b/tests/unit/tasks/test_base_task.py @@ -3,6 +3,7 @@ from griptape.artifacts import TextArtifact from griptape.structures import Agent from griptape.tasks import ActionsSubtask +from griptape.structures import Workflow from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_task import MockTask @@ -30,3 +31,40 @@ def test_meta_memories(self, task): task.structure.task_memory.process_output(MockTool().test, subtask, TextArtifact("foo")) assert len(task.meta_memories) == 2 + + def test_parent_outputs(self, task): + parent_1 = MockTask("foobar1", id="foobar1") + parent_2 = MockTask("foobar2", id="foobar2") + parent_3 = MockTask("foobar3", id="foobar3") + child = MockTask("foobar", id="foobar") + + child.add_parent(parent_1) + child.add_parent(parent_2) + child.add_parent(parent_3) + + workflow = Workflow(tasks=[parent_1, parent_2, parent_3, child]) + workflow.run() + + parent_3.output = None + assert child.parent_outputs == { + parent_1.id: parent_1.output.to_text(), + parent_2.id: parent_2.output.to_text(), + parent_3.id: "", + } + + def test_parents_output(self, task): + parent_1 = MockTask("foobar1", id="foobar1") + parent_2 = MockTask("foobar2", id="foobar2") + parent_3 = MockTask("foobar3", id="foobar3") + child = MockTask("foobar", id="foobar") + + child.add_parent(parent_1) + child.add_parent(parent_2) + child.add_parent(parent_3) + + workflow = Workflow(tasks=[parent_1, parent_2, parent_3, child]) + workflow.run() + + parent_2.output = None + + assert child.parents_output_text == "foobar1\nfoobar3" diff --git a/tests/unit/tasks/test_text_to_speech_task.py b/tests/unit/tasks/test_text_to_speech_task.py index f30893e8a..7a8e49364 100644 --- a/tests/unit/tasks/test_text_to_speech_task.py +++ b/tests/unit/tasks/test_text_to_speech_task.py @@ -1,9 +1,10 @@ from unittest.mock import Mock -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, AudioArtifact from griptape.engines import TextToSpeechEngine -from griptape.structures import Agent +from griptape.structures import Agent, Pipeline from griptape.tasks import BaseTask, TextToSpeechTask +from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_structure_config import MockStructureConfig @@ -28,3 +29,19 @@ def test_config_text_to_speech_engine(self): Agent(config=MockStructureConfig()).add_task(task) assert isinstance(task.text_to_speech_engine, TextToSpeechEngine) + + def test_calls(self): + text_to_speech_engine = Mock() + text_to_speech_engine.run.return_value = AudioArtifact(b"audio content", format="mp3") + + assert TextToSpeechTask("test", text_to_speech_engine=text_to_speech_engine).run().value == b"audio content" + + def test_run(self): + text_to_speech_engine = Mock() + text_to_speech_engine.run.return_value = AudioArtifact(b"audio content", format="mp3") + + task = TextToSpeechTask("some text", text_to_speech_engine=text_to_speech_engine) + pipeline = Pipeline(prompt_driver=MockPromptDriver()) + pipeline.add_task(task) + + assert isinstance(pipeline.run().output, AudioArtifact) diff --git a/griptape/drivers/embedding_model/__init__.py b/tests/unit/tokenizers/__init__.py similarity index 100% rename from griptape/drivers/embedding_model/__init__.py rename to tests/unit/tokenizers/__init__.py diff --git a/tests/unit/tokenizers/test_bedrock_claude_tokenizer.py b/tests/unit/tokenizers/test_amazon_bedrock_tokenizer.py similarity index 51% rename from tests/unit/tokenizers/test_bedrock_claude_tokenizer.py rename to tests/unit/tokenizers/test_amazon_bedrock_tokenizer.py index 4f6e6723f..2b77ba3dc 100644 --- a/tests/unit/tokenizers/test_bedrock_claude_tokenizer.py +++ b/tests/unit/tokenizers/test_amazon_bedrock_tokenizer.py @@ -1,19 +1,19 @@ +from griptape.tokenizers import AmazonBedrockTokenizer import pytest -from griptape.tokenizers import BedrockClaudeTokenizer -class TestBedrockClaudeTokenizer: +class TestAmazonBedrockTokenizer: @pytest.fixture def tokenizer(self, request): - return BedrockClaudeTokenizer(model=request.param) + return AmazonBedrockTokenizer(model=request.param) @pytest.mark.parametrize( "tokenizer,expected", [ - ("anthropic.claude-v2:1", 5), - ("anthropic.claude-v2", 5), - ("anthropic.claude-3-sonnet-20240229-v1:0", 5), - ("anthropic.claude-3-haiku-20240307-v1:0", 5), + ("anthropic.claude-v2:1", 4), + ("anthropic.claude-v2", 4), + ("anthropic.claude-3-sonnet-20240229-v1:0", 4), + ("anthropic.claude-3-haiku-20240307-v1:0", 4), ], indirect=["tokenizer"], ) @@ -23,10 +23,10 @@ def test_token_count(self, tokenizer, expected): @pytest.mark.parametrize( "tokenizer,expected", [ - ("anthropic.claude-v2", 99995), - ("anthropic.claude-v2:1", 199995), - ("anthropic.claude-3-sonnet-20240229-v1:0", 199995), - ("anthropic.claude-3-haiku-20240307-v1:0", 199995), + ("anthropic.claude-v2", 99996), + ("anthropic.claude-v2:1", 199996), + ("anthropic.claude-3-sonnet-20240229-v1:0", 199996), + ("anthropic.claude-3-haiku-20240307-v1:0", 199996), ], indirect=["tokenizer"], ) @@ -36,10 +36,10 @@ def test_input_tokens_left(self, tokenizer, expected): @pytest.mark.parametrize( "tokenizer,expected", [ - ("anthropic.claude-v2", 4091), - ("anthropic.claude-v2:1", 4091), - ("anthropic.claude-3-sonnet-20240229-v1:0", 4091), - ("anthropic.claude-3-haiku-20240307-v1:0", 4091), + ("anthropic.claude-v2", 4092), + ("anthropic.claude-v2:1", 4092), + ("anthropic.claude-3-sonnet-20240229-v1:0", 4092), + ("anthropic.claude-3-haiku-20240307-v1:0", 4092), ], indirect=["tokenizer"], ) diff --git a/tests/unit/tokenizers/test_base_tokenizer.py b/tests/unit/tokenizers/test_base_tokenizer.py new file mode 100644 index 000000000..eed15b9b2 --- /dev/null +++ b/tests/unit/tokenizers/test_base_tokenizer.py @@ -0,0 +1,13 @@ +import logging +from tests.mocks.mock_tokenizer import MockTokenizer + + +class TestBaseTokenizer: + def test_default_tokens(self, caplog): + with caplog.at_level(logging.WARNING): + tokenizer = MockTokenizer(model="gpt2") + + assert tokenizer.max_input_tokens == 4096 + assert tokenizer.max_output_tokens == 1000 + + assert "gpt2 not found" in caplog.text diff --git a/tests/unit/tokenizers/test_bedrock_cohere_tokenizer.py b/tests/unit/tokenizers/test_bedrock_cohere_tokenizer.py deleted file mode 100644 index 6238b0e54..000000000 --- a/tests/unit/tokenizers/test_bedrock_cohere_tokenizer.py +++ /dev/null @@ -1,25 +0,0 @@ -import pytest -from unittest import mock -from griptape.tokenizers import BedrockCohereTokenizer - - -class TestBedrockCohereTokenizer: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_tokenization = '{"inputTextTokenCount": 2}' - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_tokenization - mock_client.invoke_model.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - def test_input_tokens_left(self): - assert BedrockCohereTokenizer(model="cohere").count_input_tokens_left("foo bar") == 1022 - - def test_output_tokens_left(self): - assert BedrockCohereTokenizer(model="cohere").count_output_tokens_left("foo bar") == 4094 diff --git a/tests/unit/tokenizers/test_bedrock_jurassic_tokenizer.py b/tests/unit/tokenizers/test_bedrock_jurassic_tokenizer.py deleted file mode 100644 index 59c42493b..000000000 --- a/tests/unit/tokenizers/test_bedrock_jurassic_tokenizer.py +++ /dev/null @@ -1,39 +0,0 @@ -import pytest -from unittest import mock -from griptape.tokenizers import BedrockJurassicTokenizer - - -class TestBedrockJurassicTokenizer: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_tokenization = '{"prompt": {"tokens": [{}, {}, {}]}}' - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_tokenization - mock_client.invoke_model.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - @pytest.fixture - def tokenizer(self, request): - return BedrockJurassicTokenizer(model=request.param) - - @pytest.mark.parametrize( - "tokenizer,expected", - [("ai21.j2-mid-v1", 8186), ("ai21.j2-ultra-v1", 8186), ("ai21.j2-large-v1", 8186), ("ai21.j2-large-v2", 8186)], - indirect=["tokenizer"], - ) - def test_input_tokens_left(self, tokenizer, expected): - assert tokenizer.count_input_tokens_left("System: foo\nUser: bar\nAssistant:") == expected - - @pytest.mark.parametrize( - "tokenizer,expected", - [("ai21.j2-mid-v1", 8185), ("ai21.j2-ultra-v1", 8185), ("ai21.j2-large-v1", 8185), ("ai21.j2-large-v2", 2042)], - indirect=["tokenizer"], - ) - def test_output_tokens_left(self, tokenizer, expected): - assert tokenizer.count_output_tokens_left("System: foo\nUser: bar\nAssistant:") == expected diff --git a/tests/unit/tokenizers/test_bedrock_llama_tokenizer.py b/tests/unit/tokenizers/test_bedrock_llama_tokenizer.py deleted file mode 100644 index da842f0f3..000000000 --- a/tests/unit/tokenizers/test_bedrock_llama_tokenizer.py +++ /dev/null @@ -1,35 +0,0 @@ -import pytest -from unittest import mock -from griptape.tokenizers import BedrockLlamaTokenizer - - -class TestBedrockLlamaTokenizer: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_tokenization = '{"generation_token_count": 13}' - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_tokenization - mock_client.invoke_model.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - def test_input_tokens_left(self): - assert ( - BedrockLlamaTokenizer(model="meta.llama").count_input_tokens_left( - "[INST] <>\n{{ system_prompt }}\n<>\n\n{{ usr_msg_1 }} [/INST] {{ model_msg_1 }} [INST] {{ usr_msg_2 }} [/INST]" - ) - == 2026 - ) - - def test_ouput_tokens_left(self): - assert ( - BedrockLlamaTokenizer(model="meta.llama").count_output_tokens_left( - "[INST] <>\n{{ system_prompt }}\n<>\n\n{{ usr_msg_1 }} [/INST] {{ model_msg_1 }} [INST] {{ usr_msg_2 }} [/INST]" - ) - == 2026 - ) diff --git a/tests/unit/tokenizers/test_bedrock_titan_tokenizer.py b/tests/unit/tokenizers/test_bedrock_titan_tokenizer.py deleted file mode 100644 index c4f4f42ad..000000000 --- a/tests/unit/tokenizers/test_bedrock_titan_tokenizer.py +++ /dev/null @@ -1,31 +0,0 @@ -import pytest -from unittest import mock -from griptape.tokenizers import BedrockTitanTokenizer - - -class TestBedrockTitanTokenizer: - @pytest.fixture(autouse=True) - def mock_session(self, mocker): - fake_tokenization = '{"inputTextTokenCount": 13}' - mock_session_class = mocker.patch("boto3.Session") - - mock_session_object = mock.Mock() - mock_client = mock.Mock() - mock_response = mock.Mock() - - mock_response.get().read.return_value = fake_tokenization - mock_client.invoke_model.return_value = mock_response - mock_session_object.client.return_value = mock_client - mock_session_class.return_value = mock_session_object - - def test_input_tokens_left(self): - assert ( - BedrockTitanTokenizer(model="amazon.titan").count_input_tokens_left("Instructions: foo\nUser: bar\nBot:") - == 4090 - ) - - def test_output_tokens_left(self): - assert ( - BedrockTitanTokenizer(model="amazon.titan").count_output_tokens_left("Instructions: foo\nUser: bar\nBot:") - == 7994 - ) diff --git a/tests/unit/tokenizers/test_cohere_tokenizer.py b/tests/unit/tokenizers/test_cohere_tokenizer.py index ca724cee6..9ca23f4f0 100644 --- a/tests/unit/tokenizers/test_cohere_tokenizer.py +++ b/tests/unit/tokenizers/test_cohere_tokenizer.py @@ -7,6 +7,7 @@ class TestCohereTokenizer: @pytest.fixture(autouse=True) def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value.tokenize.return_value.tokens = ["foo", "bar"] + return mock_client @pytest.fixture diff --git a/tests/unit/tokenizers/test_google_tokenizer.py b/tests/unit/tokenizers/test_google_tokenizer.py index 2b26ec6a6..955a0517f 100644 --- a/tests/unit/tokenizers/test_google_tokenizer.py +++ b/tests/unit/tokenizers/test_google_tokenizer.py @@ -1,5 +1,6 @@ import pytest from unittest.mock import Mock +from griptape.utils import PromptStack from griptape.tokenizers import GoogleTokenizer @@ -18,6 +19,7 @@ def tokenizer(self, request): @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 5)], indirect=["tokenizer"]) def test_token_count(self, tokenizer, expected): assert tokenizer.count_tokens("foo bar huzzah") == expected + assert tokenizer.count_tokens(PromptStack(inputs=[PromptStack.Input(content="foo", role="user")])) == expected assert tokenizer.count_tokens(["foo", "bar", "huzzah"]) == expected @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 30715)], indirect=["tokenizer"]) diff --git a/tests/unit/tokenizers/test_hugging_face_tokenizer.py b/tests/unit/tokenizers/test_hugging_face_tokenizer.py index 5be74f667..dcb309a84 100644 --- a/tests/unit/tokenizers/test_hugging_face_tokenizer.py +++ b/tests/unit/tokenizers/test_hugging_face_tokenizer.py @@ -2,15 +2,14 @@ environ["TRANSFORMERS_VERBOSITY"] = "error" -import pytest -from transformers import GPT2Tokenizer -from griptape.tokenizers import HuggingFaceTokenizer +import pytest # noqa: E402 +from griptape.tokenizers import HuggingFaceTokenizer # noqa: E402 class TestHuggingFaceTokenizer: @pytest.fixture def tokenizer(self): - return HuggingFaceTokenizer(tokenizer=GPT2Tokenizer.from_pretrained("gpt2"), max_output_tokens=1024) + return HuggingFaceTokenizer(model="gpt2", max_output_tokens=1024) def test_token_count(self, tokenizer): assert tokenizer.count_tokens("foo bar huzzah") == 5 diff --git a/tests/unit/tokenizers/test_openai_tokenizer.py b/tests/unit/tokenizers/test_openai_tokenizer.py index b27080aa3..4aa42a87a 100644 --- a/tests/unit/tokenizers/test_openai_tokenizer.py +++ b/tests/unit/tokenizers/test_openai_tokenizer.py @@ -13,6 +13,7 @@ def tokenizer(self, request): ("gpt-4-1106", 5), ("gpt-4-32k", 5), ("gpt-4", 5), + ("gpt-4o", 5), ("gpt-3.5-turbo-0301", 5), ("gpt-3.5-turbo-16k", 5), ("gpt-3.5-turbo", 5), @@ -38,11 +39,13 @@ def test_initialize_with_unknown_model(self): ("gpt-4-1106", 19), ("gpt-4-32k", 19), ("gpt-4", 19), + ("gpt-4o", 19), ("gpt-3.5-turbo-0301", 21), ("gpt-3.5-turbo-16k", 19), ("gpt-3.5-turbo", 19), ("gpt-35-turbo-16k", 19), ("gpt-35-turbo", 19), + ("gpt-35-turbo", 19), ], indirect=["tokenizer"], ) @@ -54,10 +57,18 @@ def test_token_count_for_messages(self, tokenizer, expected): == expected ) + @pytest.mark.parametrize("tokenizer,expected", [("not-real-model", 19)], indirect=["tokenizer"]) + def test_token_count_for_messages_unknown_model(self, tokenizer, expected): + with pytest.raises(NotImplementedError): + tokenizer.count_tokens( + [{"role": "system", "content": "foobar baz"}, {"role": "user", "content": "how foobar am I?"}] + ) + @pytest.mark.parametrize( "tokenizer,expected", [ ("gpt-4-1106", 127987), + ("gpt-4o", 127987), ("gpt-4-32k", 32755), ("gpt-4", 8179), ("gpt-3.5-turbo-16k", 16371), @@ -80,6 +91,7 @@ def test_input_tokens_left(self, tokenizer, expected): ("gpt-4-1106", 4091), ("gpt-4-32k", 4091), ("gpt-4", 4091), + ("gpt-4o", 4091), ("gpt-3.5-turbo-16k", 4091), ("gpt-3.5-turbo", 4091), ("gpt-35-turbo-16k", 4091), diff --git a/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py b/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py index 46270d216..9feba9cbf 100644 --- a/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py +++ b/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py @@ -1,5 +1,6 @@ import pytest -from griptape.artifacts import TextArtifact +from requests import exceptions +from griptape.artifacts import TextArtifact, ErrorArtifact class TestGriptapeCloudKnowledgeBaseClient: @@ -8,10 +9,12 @@ def client(self, mocker): from griptape.tools import GriptapeCloudKnowledgeBaseClient mock_response = mocker.Mock() + mock_response.status_code = 201 mock_response.text.return_value = "foo bar" mocker.patch("requests.post", return_value=mock_response) mock_response = mocker.Mock() + mock_response.status_code = 200 mock_response.json.return_value = {"description": "fizz buzz"} mocker.patch("requests.get", return_value=mock_response) @@ -19,11 +22,63 @@ def client(self, mocker): base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" ) + @pytest.fixture + def client_no_description(self, mocker): + from griptape.tools import GriptapeCloudKnowledgeBaseClient + + mock_response = mocker.Mock() + mock_response.json.return_value = {} + mock_response.status_code = 200 + mocker.patch("requests.get", return_value=mock_response) + + return GriptapeCloudKnowledgeBaseClient( + base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" + ) + + @pytest.fixture + def client_kb_not_found(self, mocker): + from griptape.tools import GriptapeCloudKnowledgeBaseClient + + mock_response = mocker.Mock() + mock_response.json.return_value = {} + mock_response.status_code = 404 + mocker.patch("requests.get", return_value=mock_response) + + return GriptapeCloudKnowledgeBaseClient( + base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" + ) + + @pytest.fixture + def client_kb_error(self, mocker): + from griptape.tools import GriptapeCloudKnowledgeBaseClient + + mock_response = mocker.Mock() + mock_response.status_code = 500 + mocker.patch("requests.post", return_value=mock_response, side_effect=exceptions.RequestException("error")) + + return GriptapeCloudKnowledgeBaseClient( + base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" + ) + def test_query(self, client): assert isinstance(client.query({"values": {"query": "foo bar"}}), TextArtifact) + def test_query_error(self, client_kb_error): + assert isinstance(client_kb_error.query({"values": {"query": "foo bar"}}), ErrorArtifact) + assert client_kb_error.query({"values": {"query": "foo bar"}}).value == "error" + def test_get_knowledge_base_description(self, client): assert client._get_knowledge_base_description() == "fizz buzz" client.description = "foo bar" assert client._get_knowledge_base_description() == "foo bar" + + def test_get_knowledge_base_description_error(self, client_no_description): + exception_match_text = f"No description found for Knowledge Base {client_no_description.knowledge_base_id}. Please set a description, or manually set the `GriptapeCloudKnowledgeBaseClient.description` attribute." + with pytest.raises(ValueError, match=exception_match_text) as e: + client_no_description._get_knowledge_base_description() + + def test_get_knowledge_base_kb_error(self, client_kb_not_found): + exception_match_text = f"Error accessing Knowledge Base {client_kb_not_found.knowledge_base_id}." + with pytest.raises(ValueError, match=exception_match_text) as e: + client_kb_not_found._get_knowledge_base_description() diff --git a/tests/unit/tools/test_web_search.py b/tests/unit/tools/test_web_search.py index faa1056b7..c9a79b452 100644 --- a/tests/unit/tools/test_web_search.py +++ b/tests/unit/tools/test_web_search.py @@ -1,9 +1,34 @@ -from griptape.artifacts import BaseArtifact +from griptape.artifacts import BaseArtifact, ErrorArtifact from griptape.tools import WebSearch +from pytest import fixture +import json class TestWebSearch: - def test_search(self): - tool = WebSearch(google_api_key="foo", google_api_search_id="bar") + @fixture + def websearch_tool(self, mocker): + mock_response = mocker.Mock() + mock_response.status_code = 200 + mock_response.json.return_value = {"items": [{"title": "foo", "link": "bar", "snippet": "baz"}]} + mocker.patch("requests.get", return_value=mock_response) - assert isinstance(tool.search({"values": {"query": "foo bar"}}), BaseArtifact) + return WebSearch(google_api_key="foo", google_api_search_id="bar") + + @fixture + def websearch_tool_with_error(self, mocker): + mock_response = mocker.Mock() + mock_response.status_code = 500 + mocker.patch("requests.get", return_value=mock_response) + + return WebSearch(google_api_key="foo", google_api_search_id="bar") + + def test_search(self, websearch_tool): + assert isinstance(websearch_tool.search({"values": {"query": "foo bar"}}), BaseArtifact) + assert json.loads(websearch_tool.search({"values": {"query": "foo bar"}}).value[0].value) == { + "title": "foo", + "url": "bar", + "description": "baz", + } + + def test_search_with_error(self, websearch_tool_with_error): + assert isinstance(websearch_tool_with_error.search({"values": {"query": "foo bar"}}), ErrorArtifact) diff --git a/tests/unit/utils/test_prompt_stack.py b/tests/unit/utils/test_prompt_stack.py index 253e8cd44..80010abec 100644 --- a/tests/unit/utils/test_prompt_stack.py +++ b/tests/unit/utils/test_prompt_stack.py @@ -1,9 +1,5 @@ import pytest from griptape.utils import PromptStack -from tests.mocks.mock_prompt_driver import MockPromptDriver -from tests.mocks.mock_tokenizer import MockTokenizer -from griptape.structures.agent import Agent -from griptape.memory.structure import ConversationMemory, Run class TestPromptStack: @@ -43,97 +39,3 @@ def test_add_assistant_input(self, prompt_stack): assert prompt_stack.inputs[0].role == "assistant" assert prompt_stack.inputs[0].content == "foo" - - def test_add_conversation_memory_autopruing_disabled(self): - agent = Agent(prompt_driver=MockPromptDriver()) - memory = ConversationMemory( - autoprune=False, - runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), - ], - ) - memory.structure = agent - prompt_stack = PromptStack() - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") - prompt_stack.add_conversation_memory(memory) - - assert len(prompt_stack.inputs) == 12 - - def test_add_conversation_memory_autopruing_enabled(self): - # All memory is pruned. - agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=0))) - memory = ConversationMemory( - autoprune=True, - runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), - ], - ) - memory.structure = agent - prompt_stack = PromptStack() - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") - prompt_stack.add_conversation_memory(memory) - - assert len(prompt_stack.inputs) == 3 - - # No memory is pruned. - agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=1000))) - memory = ConversationMemory( - autoprune=True, - runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), - ], - ) - memory.structure = agent - prompt_stack = PromptStack() - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") - prompt_stack.add_conversation_memory(memory) - - assert len(prompt_stack.inputs) == 13 - - # One memory is pruned. - # MockTokenizer's max_input_tokens set to one below the sum of memory + system prompt tokens - # so that a single memory is pruned. - agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=160))) - memory = ConversationMemory( - autoprune=True, - runs=[ - # All of these sum to 155 tokens with the MockTokenizer. - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), - ], - ) - memory.structure = agent - prompt_stack = PromptStack() - # And then another 6 tokens from fizz for a total of 161 tokens. - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") - prompt_stack.add_conversation_memory(memory, 1) - - # We expect one run (2 prompt stack inputs) to be pruned. - assert len(prompt_stack.inputs) == 11 - assert prompt_stack.inputs[0].content == "fizz" - assert prompt_stack.inputs[1].content == "foo2" - assert prompt_stack.inputs[2].content == "bar2" - assert prompt_stack.inputs[-2].content == "foo" - assert prompt_stack.inputs[-1].content == "bar" diff --git a/tests/unit/utils/test_structure_visualizer.py b/tests/unit/utils/test_structure_visualizer.py new file mode 100644 index 000000000..d7177bf30 --- /dev/null +++ b/tests/unit/utils/test_structure_visualizer.py @@ -0,0 +1,52 @@ +from tests.mocks.mock_prompt_driver import MockPromptDriver +from griptape.utils import StructureVisualizer +from griptape.tasks import PromptTask +from griptape.structures import Agent, Workflow, Pipeline + + +class TestStructureVisualizer: + def test_agent(self): + agent = Agent(prompt_driver=MockPromptDriver(), tasks=[PromptTask("test1", id="task1")]) + + visualizer = StructureVisualizer(agent) + result = visualizer.to_url() + + assert result == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMTs=" + + def test_pipeline(self): + pipeline = Pipeline( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1"), + PromptTask("test2", id="task2"), + PromptTask("test3", id="task3"), + PromptTask("test4", id="task4"), + ], + ) + + visualizer = StructureVisualizer(pipeline) + result = visualizer.to_url() + + assert ( + result + == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMS0tPiB0YXNrMjsKCXRhc2syLS0+IHRhc2szOwoJdGFzazMtLT4gdGFzazQ7Cgl0YXNrNDs=" + ) + + def test_workflow(self): + workflow = Workflow( + prompt_driver=MockPromptDriver(), + tasks=[ + PromptTask("test1", id="task1"), + PromptTask("test2", id="task2", parent_ids=["task1"]), + PromptTask("test3", id="task3", parent_ids=["task1"]), + PromptTask("test4", id="task4", parent_ids=["task2", "task3"]), + ], + ) + + visualizer = StructureVisualizer(workflow) + result = visualizer.to_url() + + assert ( + result + == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMS0tPiB0YXNrMiAmIHRhc2szOwoJdGFzazItLT4gdGFzazQ7Cgl0YXNrMy0tPiB0YXNrNDsKCXRhc2s0Ow==" + ) diff --git a/tests/utils/structure_tester.py b/tests/utils/structure_tester.py index 4f111b8d8..8d62bc835 100644 --- a/tests/utils/structure_tester.py +++ b/tests/utils/structure_tester.py @@ -14,17 +14,10 @@ BasePromptDriver, AmazonBedrockPromptDriver, AnthropicPromptDriver, - BedrockClaudePromptModelDriver, - BedrockJurassicPromptModelDriver, - BedrockTitanPromptModelDriver, - BedrockLlamaPromptModelDriver, CoherePromptDriver, OpenAiChatPromptDriver, - OpenAiCompletionPromptDriver, AzureOpenAiChatPromptDriver, - AmazonSageMakerPromptDriver, - SageMakerLlamaPromptModelDriver, - SageMakerFalconPromptModelDriver, + AmazonSageMakerJumpstartPromptDriver, GooglePromptDriver, ) @@ -53,12 +46,6 @@ class TesterPromptDriverOption: prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo-1106", api_key=os.environ["OPENAI_API_KEY"]), enabled=True, ), - "OPENAI_CHAT_35_TURBO_INSTRUCT": TesterPromptDriverOption( - prompt_driver=OpenAiCompletionPromptDriver( - model="gpt-3.5-turbo-instruct", api_key=os.environ["OPENAI_API_KEY"] - ), - enabled=True, - ), "OPENAI_CHAT_4": TesterPromptDriverOption( prompt_driver=OpenAiChatPromptDriver(model="gpt-4", api_key=os.environ["OPENAI_API_KEY"]), enabled=True ), @@ -69,10 +56,6 @@ class TesterPromptDriverOption: prompt_driver=OpenAiChatPromptDriver(model="gpt-4-1106-preview", api_key=os.environ["OPENAI_API_KEY"]), enabled=True, ), - "OPENAI_COMPLETION_DAVINCI": TesterPromptDriverOption( - prompt_driver=OpenAiCompletionPromptDriver(api_key=os.environ["OPENAI_API_KEY"], model="text-davinci-003"), - enabled=True, - ), "AZURE_CHAT_35_TURBO": TesterPromptDriverOption( prompt_driver=AzureOpenAiChatPromptDriver( api_key=os.environ["AZURE_OPENAI_API_KEY_1"], @@ -84,10 +67,10 @@ class TesterPromptDriverOption: ), "AZURE_CHAT_35_TURBO_16K": TesterPromptDriverOption( prompt_driver=AzureOpenAiChatPromptDriver( - api_key=os.environ["AZURE_OPENAI_API_KEY_1"], + api_key=os.environ["AZURE_OPENAI_API_KEY_2"], model="gpt-35-turbo-16k", azure_deployment=os.environ["AZURE_OPENAI_35_TURBO_16K_DEPLOYMENT_ID"], - azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT_1"], + azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT_2"], ), enabled=True, ), @@ -142,71 +125,75 @@ class TesterPromptDriverOption: "COHERE_COMMAND": TesterPromptDriverOption( prompt_driver=CoherePromptDriver(model="command", api_key=os.environ["COHERE_API_KEY"]), enabled=True ), - "BEDROCK_TITAN": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="amazon.titan-tg1-large", prompt_model_driver=BedrockTitanPromptModelDriver() - ), - enabled=True, + "AMAZON_BEDROCK_ANTHROPIC_CLAUDE_3_SONNET": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="anthropic.claude-3-sonnet-20240229-v1:0"), enabled=True ), - "BEDROCK_CLAUDE_INSTANT": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="anthropic.claude-instant-v1", prompt_model_driver=BedrockClaudePromptModelDriver() - ), - enabled=True, + "AMAZON_BEDROCK_ANTHROPIC_CLAUDE_3_HAIKU": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="anthropic.claude-3-haiku-20240307-v1:0"), enabled=True ), - "BEDROCK_CLAUDE_2": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="anthropic.claude-v2", prompt_model_driver=BedrockClaudePromptModelDriver() - ), - enabled=True, + "AMAZON_BEDROCK_ANTHROPIC_CLAUDE_2": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="anthropic.claude-v2"), enabled=True ), - "BEDROCK_CLAUDE_2.1": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="anthropic.claude-v2:1", prompt_model_driver=BedrockClaudePromptModelDriver() - ), - enabled=True, + "AMAZON_BEDROCK_ANTHROPIC_CLAUDE_2.1": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="anthropic.claude-v2:1"), enabled=True ), - "BEDROCK_CLAUDE_3_SONNET": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="anthropic.claude-3-sonnet-20240229-v1:0", prompt_model_driver=BedrockClaudePromptModelDriver() - ), - enabled=True, + "AMAZON_BEDROCK_ANTHROPIC_CLAUDE_INSTANT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="anthropic.claude-instant-v1"), enabled=True ), - "BEDROCK_CLAUDE_3_HAIKU": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="anthropic.claude-3-haiku-20240307-v1:0", prompt_model_driver=BedrockClaudePromptModelDriver() - ), - enabled=True, + "AMAZON_BEDROCK_J2_ULTRA": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="ai21.j2-ultra"), enabled=True ), - "BEDROCK_J2": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="ai21.j2-ultra", prompt_model_driver=BedrockJurassicPromptModelDriver() - ), - enabled=True, + "AMAZON_BEDROCK_J2_MID": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="ai21.j2-mid"), enabled=True ), - "BEDROCK_LLAMA2_13B": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="meta.llama2-13b-chat-v1", prompt_model_driver=BedrockLlamaPromptModelDriver(), max_attempts=1 - ), - enabled=True, + "AMAZON_BEDROCK_TITAN_TEXT_LITE": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="amazon.titan-text-lite-v1"), enabled=True ), - "BEDROCK_LLAMA2_70B": TesterPromptDriverOption( - prompt_driver=AmazonBedrockPromptDriver( - model="meta.llama2-70b-chat-v1", prompt_model_driver=BedrockLlamaPromptModelDriver(), max_attempts=1 - ), - enabled=True, + "AMAZON_BEDROCK_TITAN_TEXT_EXPRESS": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="amazon.titan-text-express-v1"), enabled=True + ), + "AMAZON_BEDROCK_COHERE_COMMAND_R_PLUS": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="cohere.command-r-plus-v1:0"), enabled=True + ), + "AMAZON_BEDROCK_COHERE_COMMAND_R": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="cohere.command-r-v1:0"), enabled=True + ), + "AMAZON_BEDROCK_COHERE_COMMAND_TEXT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="cohere.command-text-v14"), enabled=True + ), + "AMAZON_BEDROCK_COHERE_COMMAND_LIGHT_TEXT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="cohere.command-light-text-v14"), enabled=True + ), + "AMAZON_BEDROCK_LLAMA3_8B_INSTRUCT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="meta.llama3-8b-instruct-v1:0"), enabled=True + ), + "AMAZON_BEDROCK_LLAMA2_13B_CHAT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="meta.llama2-13b-chat-v1"), enabled=True + ), + "AMAZON_BEDROCK_LLAMA2_70B_CHAT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="meta.llama2-70b-chat-v1"), enabled=True + ), + "AMAZON_BEDROCK_MISTRAL_7B_INSTRUCT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="mistral.mistral-7b-instruct-v0:2"), enabled=True + ), + "AMAZON_BEDROCK_MISTRAL_MIXTRAL_8X7B_INSTRUCT": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="mistral.mixtral-8x7b-instruct-v0:1"), enabled=True + ), + "AMAZON_BEDROCK_MISTRAL_LARGE_2402": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="mistral.mistral-large-2402-v1:0"), enabled=True + ), + "AMAZON_BEDROCK_MISTRAL_SMALL_2402": TesterPromptDriverOption( + prompt_driver=AmazonBedrockPromptDriver(model="mistral.mistral-small-2402-v1:0"), enabled=True ), "SAGEMAKER_LLAMA_7B": TesterPromptDriverOption( - prompt_driver=AmazonSageMakerPromptDriver( - model=os.environ["SAGEMAKER_LLAMA_ENDPOINT_NAME"], - prompt_model_driver=SageMakerLlamaPromptModelDriver(max_tokens=4096), + prompt_driver=AmazonSageMakerJumpstartPromptDriver( + endpoint=os.environ["SAGEMAKER_LLAMA_ENDPOINT_NAME"], model="meta-llama/Llama-2-7b-chat-hf" ), enabled=False, ), "SAGEMAKER_FALCON_7b": TesterPromptDriverOption( - prompt_driver=AmazonSageMakerPromptDriver( - model=os.environ["SAGEMAKER_FALCON_ENDPOINT_NAME"], - prompt_model_driver=SageMakerFalconPromptModelDriver(), + prompt_driver=AmazonSageMakerJumpstartPromptDriver( + endpoint=os.environ["SAGEMAKER_FALCON_ENDPOINT_NAME"], model="tiiuae/falcon-7b-instruct" ), enabled=False, ), @@ -221,6 +208,7 @@ class TesterPromptDriverOption: PROMPT_DRIVERS["AZURE_CHAT_4"], PROMPT_DRIVERS["AZURE_CHAT_4_32K"], PROMPT_DRIVERS["ANTHROPIC_CLAUDE_3_OPUS"], + PROMPT_DRIVERS["ANTHROPIC_CLAUDE_3_OPUS"], PROMPT_DRIVERS["GOOGLE_GEMINI_PRO"], ] ) @@ -249,7 +237,7 @@ def verify_structure_output(self, structure) -> dict: ) task_names = [task.__class__.__name__ for task in structure.tasks] prompt = structure.input_task.input.to_text() - actual = structure.output_task.output.to_text() + actual = structure.output.to_text() rules = [rule.value for ruleset in structure.input_task.all_rulesets for rule in ruleset.rules] agent = Agent( From 28a8a14a23f7e4a1d95ab8202dc2a52601531692 Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Wed, 19 Jun 2024 18:18:11 -0500 Subject: [PATCH 03/87] Update `WebSearch` to use a driver; add drivers for Google and DuckDuckGo (#869) --- CHANGELOG.md | 7 + docs/examples/multi-agent-workflow.md | 8 +- .../drivers/web-search-drivers.md | 62 +++++++++ docs/griptape-framework/structures/tasks.md | 8 +- .../official-tools/web-search.md | 13 +- griptape/drivers/__init__.py | 7 + griptape/drivers/web_search/__init__.py | 0 .../web_search/base_web_search_driver.py | 14 ++ .../duck_duck_go_web_search_driver.py | 29 ++++ .../web_search/google_web_search_driver.py | 39 ++++++ griptape/tools/web_search/tool.py | 40 +----- poetry.lock | 131 +++++++++++++++++- pyproject.toml | 4 + tests/integration/tasks/test_toolkit_task.py | 6 +- tests/unit/drivers/web_search/__init__.py | 0 .../test_duck_duck_go_web_search_driver.py | 36 +++++ .../test_google_web_search_driver.py | 43 ++++++ tests/unit/tools/test_web_search.py | 36 +++-- 18 files changed, 413 insertions(+), 70 deletions(-) create mode 100644 docs/griptape-framework/drivers/web-search-drivers.md create mode 100644 griptape/drivers/web_search/__init__.py create mode 100644 griptape/drivers/web_search/base_web_search_driver.py create mode 100644 griptape/drivers/web_search/duck_duck_go_web_search_driver.py create mode 100644 griptape/drivers/web_search/google_web_search_driver.py create mode 100644 tests/unit/drivers/web_search/__init__.py create mode 100644 tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py create mode 100644 tests/unit/drivers/web_search/test_google_web_search_driver.py diff --git a/CHANGELOG.md b/CHANGELOG.md index feec674b5..62846b623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added +- `GoogleWebSearchDriver` to web search with the Google Customsearch API. +- `DuckDuckGoWebSearchDriver` to web search with the DuckDuckGo search SDK. + +### Changed +- **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. + ## [0.27.0] - 2024-06-19 ### Added diff --git a/docs/examples/multi-agent-workflow.md b/docs/examples/multi-agent-workflow.md index d0fa65232..4a26625b3 100644 --- a/docs/examples/multi-agent-workflow.md +++ b/docs/examples/multi-agent-workflow.md @@ -7,7 +7,7 @@ Additionally, this architecture opens us up to using services such as [Griptape ```python import os -from griptape.drivers import WebhookEventListenerDriver, LocalStructureRunDriver +from griptape.drivers import WebhookEventListenerDriver, LocalStructureRunDriver, GoogleWebSearchDriver from griptape.events import EventListener, FinishStructureRunEvent from griptape.rules import Rule, Ruleset from griptape.structures import Agent, Workflow @@ -38,8 +38,10 @@ def build_researcher(): id="researcher", tools=[ WebSearch( - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + ), ), WebScraper( off_prompt=True, diff --git a/docs/griptape-framework/drivers/web-search-drivers.md b/docs/griptape-framework/drivers/web-search-drivers.md new file mode 100644 index 000000000..332ce2c2b --- /dev/null +++ b/docs/griptape-framework/drivers/web-search-drivers.md @@ -0,0 +1,62 @@ +## Overview + +Web Search Drivers can be used to search for links from a search query. They are used by [WebSearch](../../reference/griptape/tools/web_search/tool.md) to provide its functionality. All Web Search Drivers implement the following methods: + +* `search()` searchs the web and returns a [ListArtifact](../../reference/griptape/artifacts/list_artifact.md) that contains JSON-serializable [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s with the search results. + +## Google + +The [GoogleWebSearchDriver](../../reference/griptape/drivers/web_search/google_web_search_driver.md) uses the [Google Custom Search JSON API](https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list) for web searching. + +Example using `GoogleWebSearchDriver` directly: + +```python +import os +from griptape.drivers import GoogleWebSearchDriver + +driver = GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], +) + +driver.search("griptape ai") +``` + +Example of using `GoogleWebSearchDriver` with an agent: + +```python +import os +from griptape.drivers import GoogleWebSearchDriver +from griptape.tools import TaskMemoryClient, WebSearch +from griptape.structures import Agent + +agent = Agent( + tools=[ + WebSearch( + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + ), + ), + TaskMemoryClient(off_prompt=False), + ], +) +agent.run("Give me some websites with information about AI frameworks.") +``` + +## DuckDuckGo + +!!! info + This driver requires the `drivers-web-search-duckduckgo` [extra](../index.md#extras). + +The [DuckDuckGoWebSearchDriver](../../reference/griptape/drivers/web_search/duck_duck_go_web_search_driver.md) uses the [duckduckgo_search](https://github.com/deedy5/duckduckgo_search) SDK for web searching. + +Example of using `DuckDuckGoWebSearchDriver` directly: + +```python +from griptape.drivers import DuckDuckGoWebSearchDriver + +driver = DuckDuckGoWebSearchDriver() + +driver.search("griptape ai") +``` diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index 53b1b702e..c43603b1b 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -677,7 +677,7 @@ import os from griptape.rules import Rule, Ruleset from griptape.structures import Agent, Pipeline from griptape.tasks import StructureRunTask -from griptape.drivers import LocalStructureRunDriver +from griptape.drivers import LocalStructureRunDriver, GoogleWebSearchDriver from griptape.tools import ( TaskMemoryClient, WebScraper, @@ -689,8 +689,10 @@ def build_researcher(): researcher = Agent( tools=[ WebSearch( - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + ), ), WebScraper( off_prompt=True, diff --git a/docs/griptape-tools/official-tools/web-search.md b/docs/griptape-tools/official-tools/web-search.md index 2e2ea276d..b30c76038 100644 --- a/docs/griptape-tools/official-tools/web-search.md +++ b/docs/griptape-tools/official-tools/web-search.md @@ -6,14 +6,17 @@ This tool enables LLMs to search the web. import os from griptape.tools import WebSearch from griptape.structures import Agent +from griptape.drivers import GoogleWebSearchDriver # Initialize the WebSearch tool with necessary parameters web_search_tool = WebSearch( - results_count=5, - google_api_lang="lang_en", - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], - google_api_country="us", + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + results_count=5, + language="en", + country="us", + ), ) # Set up an agent using the WebSearch tool diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 8e8128d7a..3576b66bb 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -74,6 +74,10 @@ from .web_scraper.trafilatura_web_scraper_driver import TrafilaturaWebScraperDriver from .web_scraper.markdownify_web_scraper_driver import MarkdownifyWebScraperDriver +from .web_search.base_web_search_driver import BaseWebSearchDriver +from .web_search.google_web_search_driver import GoogleWebSearchDriver +from .web_search.duck_duck_go_web_search_driver import DuckDuckGoWebSearchDriver + from .event_listener.base_event_listener_driver import BaseEventListenerDriver from .event_listener.amazon_sqs_event_listener_driver import AmazonSqsEventListenerDriver from .event_listener.webhook_event_listener_driver import WebhookEventListenerDriver @@ -163,6 +167,9 @@ "BaseWebScraperDriver", "TrafilaturaWebScraperDriver", "MarkdownifyWebScraperDriver", + "BaseWebSearchDriver", + "GoogleWebSearchDriver", + "DuckDuckGoWebSearchDriver", "BaseEventListenerDriver", "AmazonSqsEventListenerDriver", "WebhookEventListenerDriver", diff --git a/griptape/drivers/web_search/__init__.py b/griptape/drivers/web_search/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/drivers/web_search/base_web_search_driver.py b/griptape/drivers/web_search/base_web_search_driver.py new file mode 100644 index 000000000..2b5662155 --- /dev/null +++ b/griptape/drivers/web_search/base_web_search_driver.py @@ -0,0 +1,14 @@ +from abc import ABC, abstractmethod +from attrs import field, define + +from griptape.artifacts import ListArtifact + + +@define +class BaseWebSearchDriver(ABC): + results_count: int = field(default=5, kw_only=True) + language: str = field(default="en", kw_only=True) + country: str = field(default="us", kw_only=True) + + @abstractmethod + def search(self, query: str, **kwargs) -> ListArtifact: ... diff --git a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py new file mode 100644 index 000000000..9b90bf5ff --- /dev/null +++ b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py @@ -0,0 +1,29 @@ +from __future__ import annotations +import json +from typing import TYPE_CHECKING +from attrs import define, field, Factory +from griptape.artifacts import TextArtifact, ListArtifact +from griptape.drivers import BaseWebSearchDriver +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from duckduckgo_search import DDGS + + +@define +class DuckDuckGoWebSearchDriver(BaseWebSearchDriver): + client: DDGS = field(default=Factory(lambda: import_optional_dependency("duckduckgo_search").DDGS()), kw_only=True) + + def search(self, query: str, **kwargs) -> ListArtifact: + try: + results = self.client.text(query, region=f"{self.language}-{self.country}", max_results=self.results_count) + return ListArtifact( + [ + TextArtifact( + json.dumps({"title": result["title"], "url": result["href"], "description": result["body"]}) + ) + for result in results + ] + ) + except Exception as e: + raise Exception(f"Error searching '{query}' with DuckDuckGo: {e}") diff --git a/griptape/drivers/web_search/google_web_search_driver.py b/griptape/drivers/web_search/google_web_search_driver.py new file mode 100644 index 000000000..631170532 --- /dev/null +++ b/griptape/drivers/web_search/google_web_search_driver.py @@ -0,0 +1,39 @@ +from attrs import define, field +from griptape.artifacts import TextArtifact, ListArtifact +from griptape.drivers import BaseWebSearchDriver +import requests +import json + + +@define +class GoogleWebSearchDriver(BaseWebSearchDriver): + api_key: str = field(default=None, kw_only=True) + search_id: str = field(default=None, kw_only=True) + + def search(self, query: str, **kwargs) -> ListArtifact: + return ListArtifact([TextArtifact(json.dumps(result)) for result in self._search_google(query, **kwargs)]) + + def _search_google(self, query: str, **kwargs) -> list[dict]: + url = ( + f"https://www.googleapis.com/customsearch/v1?" + f"key={self.api_key}&" + f"cx={self.search_id}&" + f"q={query}&" + f"start=0&" + f"lr=lang_{self.language}&" + f"num={self.results_count}&" + f"gl={self.country}" + ) + response = requests.get(url) + + if response.status_code == 200: + data = response.json() + + links = [{"url": r["link"], "title": r["title"], "description": r["snippet"]} for r in data["items"]] + + return links + else: + raise Exception( + f"Google Search API returned an error with status code " + f"{response.status_code} and reason '{response.reason}'" + ) diff --git a/griptape/tools/web_search/tool.py b/griptape/tools/web_search/tool.py index acc358342..e5dc9add7 100644 --- a/griptape/tools/web_search/tool.py +++ b/griptape/tools/web_search/tool.py @@ -1,20 +1,15 @@ from __future__ import annotations from attrs import define, field -from griptape.artifacts import TextArtifact, ErrorArtifact, ListArtifact +from griptape.artifacts import ErrorArtifact, ListArtifact from schema import Schema, Literal from griptape.tools import BaseTool from griptape.utils.decorators import activity -import requests -import json +from griptape.drivers import BaseWebSearchDriver @define class WebSearch(BaseTool): - results_count: int = field(default=5, kw_only=True) - google_api_lang: str = field(default="lang_en", kw_only=True) - google_api_key: str = field(kw_only=True) - google_api_search_id: str = field(kw_only=True) - google_api_country: str = field(default="us", kw_only=True) + web_search_driver: BaseWebSearchDriver = field(default=None, kw_only=True) @activity( config={ @@ -33,31 +28,6 @@ def search(self, props: dict) -> ListArtifact | ErrorArtifact: query = props["values"]["query"] try: - return ListArtifact([TextArtifact(json.dumps(result)) for result in self._search_google(query)]) + return self.web_search_driver.search(query) except Exception as e: - return ErrorArtifact(f"error searching Google: {e}") - - def _search_google(self, query: str) -> list[dict]: - url = ( - f"https://www.googleapis.com/customsearch/v1?" - f"key={self.google_api_key}&" - f"cx={self.google_api_search_id}&" - f"q={query}&" - f"start=0&" - f"lr={self.google_api_lang}&" - f"num={self.results_count}&" - f"gl={self.google_api_country}" - ) - response = requests.get(url) - - if response.status_code == 200: - data = response.json() - - links = [{"url": r["link"], "title": r["title"], "description": r["snippet"]} for r in data["items"]] - - return links - else: - raise Exception( - f"Google Search API returned an error with status code " - f"{response.status_code} and reason '{response.reason}'" - ) + return ErrorArtifact(f"Error searching '{query}' with {self.web_search_driver.__class__.__name__}: {e}") diff --git a/poetry.lock b/poetry.lock index b94c05b2a..fd27e153b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohttp" @@ -1231,6 +1231,26 @@ files = [ {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] +[[package]] +name = "duckduckgo-search" +version = "6.1.7" +description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine." +optional = true +python-versions = ">=3.8" +files = [ + {file = "duckduckgo_search-6.1.7-py3-none-any.whl", hash = "sha256:ec7d5becb8c392c0293ff9464938c1014896e1e14725c05adc306290a636fab2"}, + {file = "duckduckgo_search-6.1.7.tar.gz", hash = "sha256:c6fd8ba17fe9cd0a4f32e5b96984e959c3da865f9c2864bfcf82bf7ff9b7e8f0"}, +] + +[package.dependencies] +click = ">=8.1.7" +orjson = ">=3.10.5" +pyreqwest-impersonate = ">=0.4.8" + +[package.extras] +dev = ["mypy (>=1.10.0)", "pytest (>=8.2.2)", "pytest-asyncio (>=0.23.7)", "ruff (>=0.4.8)"] +lxml = ["lxml (>=5.2.2)"] + [[package]] name = "elevenlabs" version = "1.1.2" @@ -3296,6 +3316,61 @@ develop = ["black", "botocore", "coverage (<8.0.0)", "jinja2", "mock", "myst-par docs = ["aiohttp (>=3,<4)", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] kerberos = ["requests-kerberos"] +[[package]] +name = "orjson" +version = "3.10.5" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = true +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c"}, + {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96"}, + {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b"}, + {file = "orjson-3.10.5-cp310-none-win32.whl", hash = "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2"}, + {file = "orjson-3.10.5-cp310-none-win_amd64.whl", hash = "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228"}, + {file = "orjson-3.10.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5"}, + {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f"}, + {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa"}, + {file = "orjson-3.10.5-cp311-none-win32.whl", hash = "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04"}, + {file = "orjson-3.10.5-cp311-none-win_amd64.whl", hash = "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c"}, + {file = "orjson-3.10.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b"}, + {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211"}, + {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3"}, + {file = "orjson-3.10.5-cp312-none-win32.whl", hash = "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2"}, + {file = "orjson-3.10.5-cp312-none-win_amd64.whl", hash = "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5"}, + {file = "orjson-3.10.5-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e"}, + {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9"}, + {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b"}, + {file = "orjson-3.10.5-cp38-none-win32.whl", hash = "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4"}, + {file = "orjson-3.10.5-cp38-none-win_amd64.whl", hash = "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09"}, + {file = "orjson-3.10.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214"}, + {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595"}, + {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86"}, + {file = "orjson-3.10.5-cp39-none-win32.whl", hash = "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47"}, + {file = "orjson-3.10.5-cp39-none-win_amd64.whl", hash = "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7"}, + {file = "orjson-3.10.5.tar.gz", hash = "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d"}, +] + [[package]] name = "packaging" version = "24.0" @@ -4116,6 +4191,55 @@ docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"] full = ["Pillow (>=8.0.0)", "PyCryptodome", "cryptography"] image = ["Pillow (>=8.0.0)"] +[[package]] +name = "pyreqwest-impersonate" +version = "0.4.8" +description = "HTTP client that can impersonate web browsers, mimicking their headers and `TLS/JA3/JA4/HTTP2` fingerprints" +optional = true +python-versions = ">=3.8" +files = [ + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:45cad57afe4e6f56078ed9a7a90d0dc839d19d3e7a70175c80af21017f383bfb"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1986600253baf38f25fd07b8bdc1903359c26e5d34beb7d7d084845554b5664d"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cca4e6e59b9ad0cd20bad6caed3ac96992cd9c1d3126ecdfcab2c0ac2b75376"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab6b32544491ee655264dab86fc8a58e47c4f87d196b28022d4007faf971a50"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:64bd6299e7fc888bb7f7292cf3e29504c406e5d5d04afd37ca994ab8142d8ee4"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e914b650dd953b8d9b24ef56aa4ecbfc16e399227b68accd818f8bf159e0c558"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f62620e023490902feca0109f306e122e427feff7d59e03ecd22c69a89452367"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:08d4c01d76da88cfe3d7d03b311b375ce3fb5a59130f93f0637bb755d6e56ff1"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524e276bc460176c79d7ba4b9131d9db73c534586660371ebdf067749252a33"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22863bc0aaf02ca2f5d76c8130929ae680b7d82dfc1c28c1ed5f306ff626928"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8cc82d57f6a91037e64a7aa9122f909576ef2a141a42ce599958ef9f8c4bc033"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da8a053308210e44fd8349f07f45442a0691ac932f2881e98b05cf9ac404b091"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:78db05deed0b32c9c75f2b3168a3a9b7d5e36487b218cb839bfe7e2a143450cb"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9af9446d605903c2b4e94621a9093f8d8a403729bc9cbfbcb62929f8238c838f"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c55890181d8d81e66cac25a95e215dc9680645d01e9091b64449d5407ad9bc6"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69344e7ae9964502a8693da7ad77ebc3e1418ee197e2e394bc23c5d4970772a"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b5db5c957a10d8cc2815085ba0b8fe09245b2f94c2225d9653a854a03b4217e1"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03c19c21f63f9c91c590c4bbcc32cc2d8066b508c683a1d163b8c7d9816a01d5"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b8cb9471ab4b2fa7e80d3ac4e580249ff988d782f2938ad1f0428433652b170d"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8081a5ace2658be91519902bde9ddc5f94e1f850a39be196007a25e3da5bbfdc"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69eababfa3200459276acd780a0f3eaf41d1fe7c02bd169e714cba422055b5b9"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632957fa671ebb841166e40913015de457225cb73600ef250c436c280e68bf45"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2ce7ddef334b4e5c68f5ea1da1d65f686b8d84f4443059d128e0f069d3fa499a"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2503277f2a95a30e28e498570e2ed03ef4302f873054e8e21d6c0e607cbbc1d1"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8260395ef4ddae325e8b30cef0391adde7bd35e1a1decf8c729e26391f09b52d"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d8066b46d82bbaff5402d767e2f13d3449b8191c37bf8283e91d301a7159869"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9c42f6343cfbd6663fb53edc9eb9feb4ebf6186b284e22368adc1eeb6a33854"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff534f491a059e74fb7f994876df86078b4b125dbecc53c098a298ecd55fa9c6"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24a16b8d55309f0af0db9d04ff442b0c91afccf078a94809e7c3a71747a5c214"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c8fada56465fc19179404cc9d5d5e1064f5dfe27405cb052f57a5b4fe06aed1"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a3d48d5abc146fd804395713427d944757a99254350e6a651e7d776818074aee"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef1ec0e97623bc0e18469418cc4dd2c59a2d5fddcae944de61e13c0b46f910e"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91857b196de89e9b36d3f8629aa8772c0bbe7efef8334fe266956b1c192ec31c"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:63831e407487b8a21bb51f97cd86a616c291d5138f8caec16ab6019cf6423935"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c72c37b03bce9900f5dbb4f476af17253ec60c13bf7a7259f71a8dc1b036cb"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f1096165741b5c2178ab15b0eb09b5de16dd39b1cc135767d72471f0a69ce"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:70c940c0e4ef335e22a6c705b01f286ee44780b5909065d212d94d82ea2580cb"}, +] + +[package.extras] +dev = ["pytest (>=8.1.1)"] + [[package]] name = "pyright" version = "1.1.363" @@ -6070,7 +6194,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] @@ -6102,6 +6226,7 @@ drivers-vector-postgresql = ["pgvector", "psycopg2-binary"] drivers-vector-redis = ["redis"] drivers-web-scraper-markdownify = ["beautifulsoup4", "markdownify", "playwright"] drivers-web-scraper-trafilatura = ["trafilatura"] +drivers-web-search-duckduckgo = ["duckduckgo-search"] loaders-audio = ["filetype"] loaders-dataframe = ["pandas"] loaders-email = ["mail-parser"] @@ -6111,4 +6236,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "6ccbbba60b534e4756d1c36e37ce1379ee2126d37b822f186b5dbb8e8f701ff3" +content-hash = "a10478cb634e28faa788c568ec9e1ab8bd8e86b09a4e3fb96d08071e76f54c7f" diff --git a/pyproject.toml b/pyproject.toml index 0869256a9..bc2fe0451 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,6 +54,7 @@ elevenlabs = {version = "^1.1.2", optional = true} torch = {version = "^2.3.0", optional = true} pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} +duckduckgo-search = {version = "^6.1.6", optional = true} # loaders pandas = {version = "^1.3", optional = true} @@ -97,6 +98,8 @@ drivers-embedding-cohere = ["cohere"] drivers-web-scraper-trafilatura = ["trafilatura"] drivers-web-scraper-markdownify = ["playwright", "beautifulsoup4", "markdownify"] +drivers-web-search-duckduckgo = ["duckduckgo-search"] + drivers-event-listener-amazon-sqs = ["boto3"] drivers-event-listener-amazon-iot = ["boto3"] drivers-event-listener-pusher = ["pusher"] @@ -134,6 +137,7 @@ all = [ "torch", "pusher", "ollama", + "duckduckgo-search", # loaders "pandas", diff --git a/tests/integration/tasks/test_toolkit_task.py b/tests/integration/tasks/test_toolkit_task.py index 97f068c5b..a4d8c30c3 100644 --- a/tests/integration/tasks/test_toolkit_task.py +++ b/tests/integration/tasks/test_toolkit_task.py @@ -12,13 +12,15 @@ def structure_tester(self, request): import os from griptape.structures import Agent from griptape.tools import WebScraper, WebSearch, TaskMemoryClient + from griptape.drivers import GoogleWebSearchDriver return StructureTester( Agent( tools=[ WebSearch( - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], search_id=os.environ["GOOGLE_API_SEARCH_ID"] + ) ), WebScraper(off_prompt=True), TaskMemoryClient(off_prompt=False), diff --git a/tests/unit/drivers/web_search/__init__.py b/tests/unit/drivers/web_search/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py b/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py new file mode 100644 index 000000000..fcacc274c --- /dev/null +++ b/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py @@ -0,0 +1,36 @@ +import pytest +import json +from griptape.drivers import DuckDuckGoWebSearchDriver +from griptape.artifacts import ListArtifact + + +class TestDuckDuckGoWebSearchDriver: + @pytest.fixture + def driver(self, mocker): + mock_response = [ + {"title": "foo", "href": "bar", "body": "baz"}, + {"title": "foo2", "href": "bar2", "body": "baz2"}, + ] + + mocker.patch("duckduckgo_search.DDGS.text", return_value=mock_response) + + return DuckDuckGoWebSearchDriver() + + @pytest.fixture + def driver_with_error(self, mocker): + mocker.patch("duckduckgo_search.DDGS.text", side_effect=Exception("test_error")) + + return DuckDuckGoWebSearchDriver() + + def test_search_returns_results(self, driver): + results = driver.search("test") + assert isinstance(results, ListArtifact) + output = [json.loads(result.value) for result in results] + assert len(output) == 2 + assert output[0]["title"] == "foo" + assert output[0]["url"] == "bar" + assert output[0]["description"] == "baz" + + def test_search_raises_error(self, driver_with_error): + with pytest.raises(Exception, match="Error searching 'test' with DuckDuckGo: test_error"): + driver_with_error.search("test") diff --git a/tests/unit/drivers/web_search/test_google_web_search_driver.py b/tests/unit/drivers/web_search/test_google_web_search_driver.py new file mode 100644 index 000000000..9ecb92f46 --- /dev/null +++ b/tests/unit/drivers/web_search/test_google_web_search_driver.py @@ -0,0 +1,43 @@ +from pytest import fixture +import pytest +from griptape.drivers import GoogleWebSearchDriver +from griptape.artifacts import ErrorArtifact +import json +from pytest_mock import MockerFixture + + +class TestGoogleWebSearchDriver: + @fixture + def driver(self, mocker: MockerFixture): + mock_response = mocker.Mock() + mocker.patch.object( + mock_response, "json", return_value={"items": [{"title": "foo", "link": "bar", "snippet": "baz"}]} + ) + mock_response.status_code = 200 + + mocker.patch("requests.get", return_value=mock_response) + + return GoogleWebSearchDriver(api_key="test", search_id="test") + + @fixture + def driver_with_error(self, mocker: MockerFixture): + mock_response = mocker.Mock() + mock_response.status_code = 500 + mock_response.reason = "test_reason" + mocker.patch("requests.get", return_value=mock_response) + + return GoogleWebSearchDriver(api_key="test", search_id="test") + + def test_search_returns_results(self, driver): + results = driver.search("test") + output = [json.loads(result.value) for result in results] + assert len(output) == 1 + assert output[0]["title"] == "foo" + assert output[0]["url"] == "bar" + assert output[0]["description"] == "baz" + + def test_search_raises_error(self, driver_with_error): + with pytest.raises( + Exception, match="Google Search API returned an error with status code 500 and reason 'test_reason'" + ): + driver_with_error.search("test") diff --git a/tests/unit/tools/test_web_search.py b/tests/unit/tools/test_web_search.py index c9a79b452..0abc880c8 100644 --- a/tests/unit/tools/test_web_search.py +++ b/tests/unit/tools/test_web_search.py @@ -1,34 +1,32 @@ -from griptape.artifacts import BaseArtifact, ErrorArtifact +import pytest +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import WebSearch -from pytest import fixture -import json class TestWebSearch: - @fixture + @pytest.fixture def websearch_tool(self, mocker): - mock_response = mocker.Mock() - mock_response.status_code = 200 - mock_response.json.return_value = {"items": [{"title": "foo", "link": "bar", "snippet": "baz"}]} - mocker.patch("requests.get", return_value=mock_response) + mock_response = TextArtifact("test_response") + driver = mocker.Mock() + mocker.patch.object(driver, "search", return_value=mock_response) - return WebSearch(google_api_key="foo", google_api_search_id="bar") + return WebSearch(web_search_driver=driver) - @fixture + @pytest.fixture def websearch_tool_with_error(self, mocker): - mock_response = mocker.Mock() - mock_response.status_code = 500 - mocker.patch("requests.get", return_value=mock_response) + mock_response = Exception("test_error") + driver = mocker.Mock() + mocker.patch.object(driver, "search", side_effect=mock_response) - return WebSearch(google_api_key="foo", google_api_search_id="bar") + return WebSearch(web_search_driver=driver) def test_search(self, websearch_tool): assert isinstance(websearch_tool.search({"values": {"query": "foo bar"}}), BaseArtifact) - assert json.loads(websearch_tool.search({"values": {"query": "foo bar"}}).value[0].value) == { - "title": "foo", - "url": "bar", - "description": "baz", - } + assert websearch_tool.search({"values": {"query": "foo bar"}}).value == "test_response" def test_search_with_error(self, websearch_tool_with_error): assert isinstance(websearch_tool_with_error.search({"values": {"query": "foo bar"}}), ErrorArtifact) + assert ( + websearch_tool_with_error.search({"values": {"query": "foo bar"}}).value + == "Error searching 'foo bar' with Mock: test_error" + ) From 73c1d51bfb1ae110bae12f5e79c8e0cf0ca40016 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 19 Jun 2024 16:42:28 -0700 Subject: [PATCH 04/87] Fix/drivers headers (#881) --- .../drivers/audio-transcription-drivers.md | 2 ++ .../drivers/conversation-memory-drivers.md | 2 ++ .../drivers/image-generation-drivers.md | 2 ++ .../drivers/image-query-drivers.md | 14 ++++++++------ docs/griptape-framework/drivers/sql-drivers.md | 8 +++++--- .../drivers/structure-run-drivers.md | 6 ++++-- .../drivers/text-to-speech-drivers.md | 2 ++ .../drivers/vector-store-drivers.md | 18 ++++++++++-------- .../drivers/web-scraper-drivers.md | 6 ++++-- .../engines/summary-engines.md | 2 +- 10 files changed, 40 insertions(+), 22 deletions(-) diff --git a/docs/griptape-framework/drivers/audio-transcription-drivers.md b/docs/griptape-framework/drivers/audio-transcription-drivers.md index ddadcb89a..c89ef9699 100644 --- a/docs/griptape-framework/drivers/audio-transcription-drivers.md +++ b/docs/griptape-framework/drivers/audio-transcription-drivers.md @@ -6,6 +6,8 @@ This driver acts as a critical bridge between audio transcription Engines and th This capability is essential for enhancing accessibility, improving content discoverability, and automating tasks that traditionally relied on manual transcription, thereby streamlining operations and enhancing efficiency across various industries. +## Audio Transcription Drivers + ### OpenAI The [OpenAI Audio Transcription Driver](../../reference/griptape/drivers/audio_transcription/openai_audio_transcription_driver.md) utilizes OpenAI's sophisticated `whisper` model to accurately transcribe spoken audio into text. This model supports multiple languages, ensuring precise transcription across a wide range of dialects. diff --git a/docs/griptape-framework/drivers/conversation-memory-drivers.md b/docs/griptape-framework/drivers/conversation-memory-drivers.md index 2ca5f8dd3..4e437a3f5 100644 --- a/docs/griptape-framework/drivers/conversation-memory-drivers.md +++ b/docs/griptape-framework/drivers/conversation-memory-drivers.md @@ -2,6 +2,8 @@ You can persist and load memory by using Conversation Memory Drivers. You can build drivers for your own data stores by extending [BaseConversationMemoryDriver](../../reference/griptape/drivers/memory/conversation/base_conversation_memory_driver.md). +## Conversation Memory Drivers + ### Local The [LocalConversationMemoryDriver](../../reference/griptape/drivers/memory/conversation/local_conversation_memory_driver.md) allows you to persist Conversation Memory in a local JSON file. diff --git a/docs/griptape-framework/drivers/image-generation-drivers.md b/docs/griptape-framework/drivers/image-generation-drivers.md index 25572ba9c..95a8bf49b 100644 --- a/docs/griptape-framework/drivers/image-generation-drivers.md +++ b/docs/griptape-framework/drivers/image-generation-drivers.md @@ -23,6 +23,8 @@ agent = Agent(tools=[ agent.run("Generate a watercolor painting of a dog riding a skateboard") ``` +## Image Generation Drivers + ### Amazon Bedrock The [Amazon Bedrock Image Generation Driver](../../reference/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.md) provides multi-model access to image generation models hosted by Amazon Bedrock. This Driver manages API calls to the Bedrock API, while the specific Model Drivers below format the API requests and parse the responses. diff --git a/docs/griptape-framework/drivers/image-query-drivers.md b/docs/griptape-framework/drivers/image-query-drivers.md index 8003924b1..720aa1819 100644 --- a/docs/griptape-framework/drivers/image-query-drivers.md +++ b/docs/griptape-framework/drivers/image-query-drivers.md @@ -1,11 +1,13 @@ -# Image Query Drivers +## Overview Image Query Drivers are used by [Image Query Engines](../engines/query-engines.md#image) to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular Image Query Driver. !!! info All Image Query Drivers default to a `max_tokens` of 256. It is recommended that you set this value to correspond to the desired response length. -## Anthropic +## Image Query Drivers + +### Anthropic !!! info To tune `max_tokens`, see [Anthropic's documentation on image tokens](https://docs.anthropic.com/claude/docs/vision#image-costs) for more information on how to relate token count to response length. @@ -59,7 +61,7 @@ result = engine.run("Describe the weather in the image", [image_artifact1, image print(result) ``` -## OpenAI +### OpenAI !!! info While the `max_tokens` field is optional, it is recommended to set this to a value that corresponds to the desired response length. Without an explicit value, the model will default to very short responses. See [OpenAI's documentation](https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them) for more information on how to relate token count to response length. @@ -86,7 +88,7 @@ with open("tests/resources/mountain.png", "rb") as f: engine.run("Describe the weather in the image", [image_artifact]) ``` -## Azure OpenAI +### Azure OpenAI !!! info In order to use the `gpt-4-vision-preview` model on Azure OpenAI, the `gpt-4` model must be deployed with the version set to `vision-preview`. More information can be found in the [Azure OpenAI documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/gpt-with-vision). @@ -117,11 +119,11 @@ with open("tests/resources/mountain.png", "rb") as f: engine.run("Describe the weather in the image", [image_artifact]) ``` -## Amazon Bedrock +### Amazon Bedrock The [Amazon Bedrock Image Query Driver](../../reference/griptape/drivers/image_query/amazon_bedrock_image_query_driver.md) provides multi-model access to image query models hosted by Amazon Bedrock. This Driver manages API calls to the Bedrock API, while the specific Model Drivers below format the API requests and parse the responses. -### Claude +#### Claude The [BedrockClaudeImageQueryModelDriver](../../reference/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.md) provides support for Claude models hosted by Bedrock. diff --git a/docs/griptape-framework/drivers/sql-drivers.md b/docs/griptape-framework/drivers/sql-drivers.md index c4b7dbcca..c0f8e9f99 100644 --- a/docs/griptape-framework/drivers/sql-drivers.md +++ b/docs/griptape-framework/drivers/sql-drivers.md @@ -8,7 +8,9 @@ SQL drivers can be used to make SQL queries and load table schemas. They are use !!! info More database-specific SQL drivers are coming soon. -## SQL +## SQL Drivers + +### SQL This is a basic SQL loader based on [SQLAlchemy 1.x](https://docs.sqlalchemy.org/en/14/). Here is an example of how to use it: @@ -22,7 +24,7 @@ driver = SqlDriver( driver.execute_query("select 'foo', 'bar';") ``` -## Amazon Redshift +### Amazon Redshift !!! info This driver requires the `drivers-sql-redshift` [extra](../index.md#extras). @@ -46,7 +48,7 @@ driver = AmazonRedshiftSqlDriver( driver.execute_query("select * from people;") ``` -## Snowflake +### Snowflake !!! info This driver requires the `drivers-sql-snowflake` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/structure-run-drivers.md b/docs/griptape-framework/drivers/structure-run-drivers.md index 54413c3a2..bba3de524 100644 --- a/docs/griptape-framework/drivers/structure-run-drivers.md +++ b/docs/griptape-framework/drivers/structure-run-drivers.md @@ -2,7 +2,9 @@ Structure Run Drivers can be used to run Griptape Structures in a variety of runtime environments. When combined with the [Structure Run Task](../../griptape-framework/structures/tasks.md#structure-run-task) or [Structure Run Client](../../griptape-tools/official-tools/structure-run-client.md) you can create complex, multi-agent pipelines that span multiple runtime environments. -## Local +## Structure Run Drivers + +### Local The [LocalStructureRunDriver](../../reference/griptape/drivers/structure_run/local_structure_run_driver.md) is used to run Griptape Structures in the same runtime environment as the code that is running the Structure. @@ -53,7 +55,7 @@ joke_coordinator = Pipeline( joke_coordinator.run("Tell me a joke") ``` -## Griptape Cloud +### Griptape Cloud The [GriptapeCloudStructureRunDriver](../../reference/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.md) is used to run Griptape Structures in the Griptape Cloud. diff --git a/docs/griptape-framework/drivers/text-to-speech-drivers.md b/docs/griptape-framework/drivers/text-to-speech-drivers.md index a37d4d33e..5f1823fdc 100644 --- a/docs/griptape-framework/drivers/text-to-speech-drivers.md +++ b/docs/griptape-framework/drivers/text-to-speech-drivers.md @@ -4,6 +4,8 @@ Provide a Driver when building an [Engine](../engines/audio-engines.md), then pass it to a [Tool](../tools/index.md) for use by an [Agent](../structures/agents.md): +## Text to Speech Drivers + ### Eleven Labs The [Eleven Labs Text to Speech Driver](../../reference/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.md) provides support for text-to-speech models hosted by Eleven Labs. This Driver supports configurations specific to Eleven Labs, like voice selection and output format. diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 481a2dd84..96480527a 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -16,7 +16,9 @@ Each vector driver takes a [BaseEmbeddingDriver](../../reference/griptape/driver !!! info More vector drivers are coming soon. -## Local +## Vector Store Drivers + +### Local The [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) can be used to load and query data from memory. Here is a complete example of how the driver can be used to load a webpage into the driver and query it later: @@ -47,7 +49,7 @@ print("\n\n".join(values)) ``` -## Pinecone +### Pinecone !!! info This driver requires the `drivers-vector-pinecone` [extra](../index.md#extras). @@ -103,7 +105,7 @@ result = vector_store_driver.query( ) ``` -## Marqo +### Marqo !!! info This driver requires the `drivers-vector-marqo` [extra](../index.md#extras). @@ -157,7 +159,7 @@ result = vector_store.query(query="What is griptape?") print(result) ``` -## Mongodb Atlas +### Mongodb Atlas !!! info This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). @@ -225,7 +227,7 @@ The format for creating a vector index should look similar to the following: ``` Replace `path_to_vector` with the expected field name where the vector content will be. -## Azure MongoDB +### Azure MongoDB !!! info This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). @@ -274,7 +276,7 @@ result = vector_store.query(query="What is griptape?") print(result) ``` -## Redis +### Redis !!! info This driver requires the `drivers-vector-redis` [extra](../index.md#extras). @@ -319,7 +321,7 @@ The format for creating a vector index should be similar to the following: FT.CREATE idx:griptape ON hash PREFIX 1 "griptape:" SCHEMA namespace TAG vector VECTOR FLAT 6 TYPE FLOAT32 DIM 1536 DISTANCE_METRIC COSINE ``` -## OpenSearch +### OpenSearch !!! info This driver requires the `drivers-vector-opensearch` [extra](../index.md#extras). @@ -372,7 +374,7 @@ The body mappings for creating a vector index should look similar to the followi } ``` -## PGVector +### PGVector !!! info This driver requires the `drivers-vector-postgresql` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/web-scraper-drivers.md b/docs/griptape-framework/drivers/web-scraper-drivers.md index a02365b67..c6835e1b5 100644 --- a/docs/griptape-framework/drivers/web-scraper-drivers.md +++ b/docs/griptape-framework/drivers/web-scraper-drivers.md @@ -4,7 +4,9 @@ Web Scraper Drivers can be used to scrape text from the web. They are used by [W * `scrape_url()` scrapes text from a website and returns a [TextArtifact](../../reference/griptape/artifacts/text_artifact.md). The format of the scrapped text is determined by the Driver. -## Markdownify +## Web Scraper Drivers + +### Markdownify !!! info This driver requires the `drivers-web-scraper-markdownify` [extra](../index.md#extras) and the @@ -64,7 +66,7 @@ agent = Agent( agent.run("List all email addresses on griptape.ai in a flat numbered markdown list.") ``` -## Trafilatura +### Trafilatura !!! info This driver requires the `drivers-web-scraper-trafilatura` [extra](../index.md#extras). diff --git a/docs/griptape-framework/engines/summary-engines.md b/docs/griptape-framework/engines/summary-engines.md index 936c12a7c..e6960c0fb 100644 --- a/docs/griptape-framework/engines/summary-engines.md +++ b/docs/griptape-framework/engines/summary-engines.md @@ -4,7 +4,7 @@ Summary engines are used to summarize text and collections of [TextArtifact](../ ## Prompt -Used to summarize texts with LLMs. You can set a custom [prompt_driver](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.prompt_driver), [template_generator](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.template_generator), and [chunker](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.chunker). +Used to summarize texts with LLMs. You can set a custom [prompt_driver](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.prompt_driver), [system_template_generator](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.system_template_generator), [user_template_generator](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.user_template_generator), and [chunker](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.chunker). Use the [summarize_artifacts](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.summarize_artifacts) method to summarize a list of artifacts or [summarize_text](../../reference/griptape/engines/summary/base_summary_engine.md#griptape.engines.summary.base_summary_engine.BaseSummaryEngine.summarize_text) to summarize an arbitrary string. From 0ef63ce7e272154c9f22be4209d7f462d3f81535 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 20 Jun 2024 12:02:52 -0700 Subject: [PATCH 05/87] Tool Task Hotfix (#883) --- CHANGELOG.md | 6 ++++++ griptape/mixins/activity_mixin.py | 3 ++- griptape/templates/tasks/tool_task/system.j2 | 2 +- tests/unit/mixins/test_activity_mixin.py | 4 ++-- tests/unit/tasks/test_tool_task.py | 2 ++ tests/unit/tasks/test_toolkit_task.py | 2 ++ tests/unit/tools/test_base_tool.py | 2 ++ 7 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bf9ea5b22..83779a833 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.27.1] - 2024-06-20 + +### Changed +- Base Tool schema so that `input` is optional when no Tool Activity schema is set. +- Tool Task system prompt for better results with lower-end models. + ## [0.27.0] - 2024-06-19 ### Added diff --git a/griptape/mixins/activity_mixin.py b/griptape/mixins/activity_mixin.py index 73810864f..9dc605543 100644 --- a/griptape/mixins/activity_mixin.py +++ b/griptape/mixins/activity_mixin.py @@ -2,6 +2,7 @@ from typing import Optional, Callable from attrs import define, field from jinja2 import Template +import schema from schema import Schema, Literal @@ -89,7 +90,7 @@ def activity_to_input(self, activity: Callable) -> dict: if self.activity_schema(activity): return {Literal("input"): {"values": getattr(activity, "config")["schema"]}} else: - return {} + return {schema.Optional("input"): {}} def _validate_tool_activity(self, activity_name): tool = self.__class__ diff --git a/griptape/templates/tasks/tool_task/system.j2 b/griptape/templates/tasks/tool_task/system.j2 index 7a802d989..996f89e1f 100644 --- a/griptape/templates/tasks/tool_task/system.j2 +++ b/griptape/templates/tasks/tool_task/system.j2 @@ -1,4 +1,4 @@ -You must respond to requests by using the following Action Schema. Your response should be a plain JSON object that successfully validates against the schema. The schema is provided below. If you can't use the Action Schema, say "I don't know how to respond." +You must respond to requests by using the following Action Schema. Your response must ONLY be a plain JSON object that successfully validates against the schema. The schema is provided below: Action Schema: {{ action_schema }} {% if meta_memory %} diff --git a/tests/unit/mixins/test_activity_mixin.py b/tests/unit/mixins/test_activity_mixin.py index 88b1f667d..c27568c21 100644 --- a/tests/unit/mixins/test_activity_mixin.py +++ b/tests/unit/mixins/test_activity_mixin.py @@ -1,5 +1,5 @@ import pytest -from schema import Schema, Literal +from schema import Schema, Literal, Optional from tests.mocks.mock_tool.tool import MockTool @@ -79,4 +79,4 @@ def test_activity_to_input(self, tool): ) input = tool.activity_to_input(tool.test_no_schema) - assert input == {} + assert input == {Optional("input"): {}} diff --git a/tests/unit/tasks/test_tool_task.py b/tests/unit/tasks/test_tool_task.py index 6ae7300f9..efab408fe 100644 --- a/tests/unit/tasks/test_tool_task.py +++ b/tests/unit/tasks/test_tool_task.py @@ -69,6 +69,7 @@ class TestToolTask: "name": {"const": "MockTool"}, "path": {"description": "test description", "const": "test_list_output"}, "tag": {"description": "Unique tag name for action execution.", "type": "string"}, + "input": {"additionalProperties": False, "properties": {}, "required": [], "type": "object"}, }, "required": ["name", "path", "tag"], "additionalProperties": False, @@ -79,6 +80,7 @@ class TestToolTask: "name": {"const": "MockTool"}, "path": {"description": "test description", "const": "test_no_schema"}, "tag": {"description": "Unique tag name for action execution.", "type": "string"}, + "input": {"additionalProperties": False, "properties": {}, "required": [], "type": "object"}, }, "required": ["name", "path", "tag"], "additionalProperties": False, diff --git a/tests/unit/tasks/test_toolkit_task.py b/tests/unit/tasks/test_toolkit_task.py index bba94f82d..f63b06d5b 100644 --- a/tests/unit/tasks/test_toolkit_task.py +++ b/tests/unit/tasks/test_toolkit_task.py @@ -71,6 +71,7 @@ class TestToolkitSubtask: "name": {"const": "MockTool"}, "path": {"description": "test description", "const": "test_list_output"}, "tag": {"description": "Unique tag name for action execution.", "type": "string"}, + "input": {"additionalProperties": False, "properties": {}, "required": [], "type": "object"}, }, "required": ["name", "path", "tag"], "additionalProperties": False, @@ -81,6 +82,7 @@ class TestToolkitSubtask: "name": {"const": "MockTool"}, "path": {"description": "test description", "const": "test_no_schema"}, "tag": {"description": "Unique tag name for action execution.", "type": "string"}, + "input": {"additionalProperties": False, "properties": {}, "required": [], "type": "object"}, }, "required": ["name", "path", "tag"], "additionalProperties": False, diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index a8fc55cc2..082973bcb 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -63,6 +63,7 @@ class TestBaseTool: "properties": { "name": {"const": "MockTool"}, "path": {"description": "test description", "const": "test_list_output"}, + "input": {"additionalProperties": False, "properties": {}, "required": [], "type": "object"}, }, "required": ["name", "path"], "additionalProperties": False, @@ -72,6 +73,7 @@ class TestBaseTool: "properties": { "name": {"const": "MockTool"}, "path": {"description": "test description", "const": "test_no_schema"}, + "input": {"additionalProperties": False, "properties": {}, "required": [], "type": "object"}, }, "required": ["name", "path"], "additionalProperties": False, From 3c37b32603cfa8055e06f0b123d2d4acf924cc0c Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 20 Jun 2024 12:57:44 -0700 Subject: [PATCH 06/87] Feature/claude sonnet (#884) --- CHANGELOG.md | 4 + .../config/amazon_bedrock_structure_config.py | 4 +- griptape/config/anthropic_structure_config.py | 2 +- poetry.lock | 79 ++++++++++++++++++- pyproject.toml | 2 +- .../test_amazon_bedrock_structure_config.py | 4 +- .../config/test_anthropic_structure_config.py | 2 +- 7 files changed, 86 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83779a833..a6ef78793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.27.1] - 2024-06-20 +### Added +- Support for Claude 3.5 Sonnet in `AnthropicPromptDriver` and `AmazonBedrockPromptDriver`. + ### Changed - Base Tool schema so that `input` is optional when no Tool Activity schema is set. - Tool Task system prompt for better results with lower-end models. +- Default Prompt Driver model to Claude 3.5 Sonnet in `AnthropicStructureConfig` and `AmazonBedrockStructureConfig.` ## [0.27.0] - 2024-06-19 diff --git a/griptape/config/amazon_bedrock_structure_config.py b/griptape/config/amazon_bedrock_structure_config.py index e70d9c819..0fa807125 100644 --- a/griptape/config/amazon_bedrock_structure_config.py +++ b/griptape/config/amazon_bedrock_structure_config.py @@ -20,7 +20,7 @@ class AmazonBedrockStructureConfig(StructureConfig): prompt_driver: BasePromptDriver = field( default=Factory( - lambda: AmazonBedrockPromptDriver(model="anthropic.claude-3-sonnet-20240229-v1:0", stream=False) + lambda: AmazonBedrockPromptDriver(model="anthropic.claude-3-5-sonnet-20240620-v1:0", stream=False) ), metadata={"serializable": True}, ) @@ -36,7 +36,7 @@ class AmazonBedrockStructureConfig(StructureConfig): image_query_driver: BaseImageGenerationDriver = field( default=Factory( lambda: AmazonBedrockImageQueryDriver( - model="anthropic.claude-3-sonnet-20240229-v1:0", + model="anthropic.claude-3-5-sonnet-20240620-v1:0", image_query_model_driver=BedrockClaudeImageQueryModelDriver(), ) ), diff --git a/griptape/config/anthropic_structure_config.py b/griptape/config/anthropic_structure_config.py index 8984300a5..28bb5f657 100644 --- a/griptape/config/anthropic_structure_config.py +++ b/griptape/config/anthropic_structure_config.py @@ -16,7 +16,7 @@ @define class AnthropicStructureConfig(StructureConfig): prompt_driver: BasePromptDriver = field( - default=Factory(lambda: AnthropicPromptDriver(model="claude-3-opus-20240229")), + default=Factory(lambda: AnthropicPromptDriver(model="claude-3-5-sonnet-20240620")), metadata={"serializable": True}, kw_only=True, ) diff --git a/poetry.lock b/poetry.lock index b94c05b2a..cb6d0ed99 100644 --- a/poetry.lock +++ b/poetry.lock @@ -123,19 +123,20 @@ frozenlist = ">=1.1.0" [[package]] name = "anthropic" -version = "0.20.0" +version = "0.29.0" description = "The official Python library for the anthropic API" optional = true python-versions = ">=3.7" files = [ - {file = "anthropic-0.20.0-py3-none-any.whl", hash = "sha256:754fe24596efbe1d7a49d3d59818a2a25d2bf29539e036eafd8a43427cd58134"}, - {file = "anthropic-0.20.0.tar.gz", hash = "sha256:f9f1a5213af4710d6e1f9b83208a4b158355d1a95eb4ae0906c7580aa0e0f1d1"}, + {file = "anthropic-0.29.0-py3-none-any.whl", hash = "sha256:d16010715129c8bc3295b74fbf4da73cfb156618bf0abb2d007255983266b76a"}, + {file = "anthropic-0.29.0.tar.gz", hash = "sha256:3eb558a232d83bdf7cdedb75663bf7ff7a8b50cc10acaa9ce6494ff295b8506a"}, ] [package.dependencies] anyio = ">=3.5.0,<5" distro = ">=1.7.0,<2" httpx = ">=0.23.0,<1" +jiter = ">=0.4.0,<1" pydantic = ">=1.9.0,<3" sniffio = "*" tokenizers = ">=0.13.0" @@ -2122,6 +2123,76 @@ MarkupSafe = ">=2.0" [package.extras] i18n = ["Babel (>=2.7)"] +[[package]] +name = "jiter" +version = "0.4.2" +description = "Fast iterable JSON parser." +optional = true +python-versions = ">=3.8" +files = [ + {file = "jiter-0.4.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:c2b003ff58d14f5e182b875acd5177b2367245c19a03be9a2230535d296f7550"}, + {file = "jiter-0.4.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b48c77c25f094707731cd5bad6b776046846b60a27ee20efc8fadfb10a89415f"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f50ad6b172bde4d45f4d4ea10c49282a337b8bb735afc99763dfa55ea84a743"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95f6001e86f525fbbc9706db2078dc22be078b0950de55b92d37041930f5f940"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16646ef23b62b007de80460d303ebb2d81e355dac9389c787cec87cdd7ffef2f"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b4e847c13b0bf1255c711a92330e7a8cb8b5cdd1e37d7db309627bcdd3367ff"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c536589be60e4c5f2b20fadc4db7e9f55d4c9df3551f29ddf1c4a18dcc9dd54"}, + {file = "jiter-0.4.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3b2763996167830889a854b4ded30bb90897f9b76be78069c50c3ec4540950e"}, + {file = "jiter-0.4.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:675e8ab98c99495091af6b6e9bf2b6353bcf81f25ab6ce27d36127e315b4505d"}, + {file = "jiter-0.4.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e48e43d9d999aaf55f53406b8846ff8cbe3e47ee4b9dc37e5a10a65ce760809f"}, + {file = "jiter-0.4.2-cp310-none-win32.whl", hash = "sha256:881b6e67c50bc36acb3570eda693763c8cd77d590940e06fa6d325d0da52ec1b"}, + {file = "jiter-0.4.2-cp310-none-win_amd64.whl", hash = "sha256:bb8f7b43259efc6add0d721ade2953e064b24e2026d26d979bc09ec080844cef"}, + {file = "jiter-0.4.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:24ad336ac47f274fa83f6fbedcabff9d3387c80f67c66b992688e6a8ba2c47e9"}, + {file = "jiter-0.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fc392a220095730afe365ce1516f2f88bb085a2fd29ea191be9c6e3c71713d9a"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c1fdc408de36c81460896de0176f2f7b9f3574dcd35693a0b2c00f4ca34c98e4"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c10ad76722ee6a8c820b0db06a793c08b7d679e5201b9563015bd1e06c959a09"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dbb46d1e9c82bba87f0cbda38413e49448a7df35b1e55917124bff9f38974a23"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:194e28ef4b5f3b61408cb2ee6b6dcbcdb0c9063d01b92b01345b7605692849f5"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f0a447533eccd62748a727e058efa10a8d7cf1de8ffe1a4d705ecb41dad9090"}, + {file = "jiter-0.4.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5f7704d7260bbb88cca3453951af739589132b26e896a3144fa2dae2263716d7"}, + {file = "jiter-0.4.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:01427458bc9550f2eda09d425755330e7d0eb09adce099577433bebf05d28d59"}, + {file = "jiter-0.4.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:159b8416879c0053b17c352f70b67b749ef5b2924c6154318ecf71918aab0905"}, + {file = "jiter-0.4.2-cp311-none-win32.whl", hash = "sha256:f2445234acfb79048ce1a0d5d0e181abb9afd9e4a29d8d9988fe26cc5773a81a"}, + {file = "jiter-0.4.2-cp311-none-win_amd64.whl", hash = "sha256:e15a65f233b6b0e5ac10ddf3b97ceb18aa9ffba096259961641d78b4ee321bd5"}, + {file = "jiter-0.4.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d61d59521aea9745447ce50f74d39a16ef74ec9d6477d9350d77e75a3d774ad2"}, + {file = "jiter-0.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eef607dc0acc251923427808dbd017f1998ae3c1a0430a261527aa5cbb3a942"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:af6bf39954646e374fc47429c656372ac731a6a26b644158a5a84bcdbed33a47"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8f509d23606e476852ee46a2b65b5c4ad3905f17424d9cc19c1dffa1c94ba3c6"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59672774daa44ee140aada0c781c82bee4d9ac5e522966186cfb6b3c217d8a51"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:24a0458efac5afeca254cf557b8a654e17013075a69905c78f88d557f129d871"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8860766d1c293e75c1bb4e25b74fa987e3adf199cac3f5f9e6e49c2bebf092f"}, + {file = "jiter-0.4.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a109f3281b72bbf4921fe43db1005c004a38559ca0b6c4985add81777dfe0a44"}, + {file = "jiter-0.4.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:faa7e667454b77ad2f0ef87db39f4944de759617aadf210ea2b73f26bb24755f"}, + {file = "jiter-0.4.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3512f8b00cafb6780b427cb6282800d2bf8277161d9c917830661bd4ed1d3528"}, + {file = "jiter-0.4.2-cp312-none-win32.whl", hash = "sha256:853b35d508ee5b66d06630473c1c0b7bb5e29bf4785c9d2202437116c94f7e21"}, + {file = "jiter-0.4.2-cp312-none-win_amd64.whl", hash = "sha256:4a3a8197784278eb8b24cb02c45e1cad67c2ce5b5b758adfb19b87f74bbdff9c"}, + {file = "jiter-0.4.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ca2a4d750aed3154b89f2efb148609fc985fad8db739460797aaf9b478acedda"}, + {file = "jiter-0.4.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0e6c304b3cc6896256727e1fb8991c7179a345eca8224e201795e9cacf4683b0"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7cc34ac708ae1750d077e490321761ec4b9a055b994cbdd1d6fbd37099e4aa7b"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8c93383875ab8d2e4f760aaff335b4a12ff32d4f9cf49c4498d657734f611466"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce197ee044add576afca0955b42142dd0312639adb6ebadbdbe4277f2855614f"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a427716813ff65480ca5b5117cfa099f49b49cd38051f8609bd0d5493013ca0"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:479990218353356234669e70fac53e5eb6f739a10db25316171aede2c97d9364"}, + {file = "jiter-0.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d35a91ec5ac74cf33234c431505299fa91c0a197c2dbafd47400aca7c69489d4"}, + {file = "jiter-0.4.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b27189847193708c94ad10ca0d891309342ae882725d2187cf5d2db02bde8d1b"}, + {file = "jiter-0.4.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:76c255308cd1093fb411a03756b7bb220e48d4a98c30cbc79ed448bf3978e27d"}, + {file = "jiter-0.4.2-cp38-none-win32.whl", hash = "sha256:bb77438060bad49cc251941e6701b31138365c8a0ddaf10cdded2fcc6dd30701"}, + {file = "jiter-0.4.2-cp38-none-win_amd64.whl", hash = "sha256:ce858af19f7ce0d4b51c9f6c0c9d08f1e9dcef1986c5875efd0674a7054292ca"}, + {file = "jiter-0.4.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:6128838a2f357b3921b2a3242d5dc002ae4255ecc8f9f05c20d56d7d2d79c5ad"}, + {file = "jiter-0.4.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f2420cebb9ba856cb57dcab1d2d8def949b464b0db09c22a4e4dbd52fff7b200"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5d13d8128e853b320e00bb18bd4bb8b136cc0936091dc87633648fc688eb705"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eba5d6e54f149c508ba88677f97d3dc7dd75e9980d234bbac8027ac6db0763a3"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0fad5d64af0bc0545237419bf4150d8de56f0bd217434bdd1a59730327252bef"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d179e7bca89cf5719bd761dd37a341ff0f98199ecaa9c14af09792e47e977cc"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36353caee9f103d8ee7bda077f6400505b0f370e27eabcab33a33d21de12a2a6"}, + {file = "jiter-0.4.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dd146c25bce576ca5db64fc7eccb8862af00f1f0e30108796953f12a53660e4c"}, + {file = "jiter-0.4.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:14b7c08cadbcd703041c66dc30e24e17de2f340281cac0e69374223ecf153aa4"}, + {file = "jiter-0.4.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a90f1a8b3d29aea198f8ea2b01148276ced8056e5103f32525266b3d880e65c9"}, + {file = "jiter-0.4.2-cp39-none-win32.whl", hash = "sha256:25b174997c780337b61ae57b1723455eecae9a17a9659044fd3c3b369190063f"}, + {file = "jiter-0.4.2-cp39-none-win_amd64.whl", hash = "sha256:bef62cea18521c5b99368147040c7e560c55098a35c93456f110678a2d34189a"}, + {file = "jiter-0.4.2.tar.gz", hash = "sha256:29b9d44f23f0c05f46d482f4ebf03213ee290d77999525d0975a17f875bf1eea"}, +] + [[package]] name = "jmespath" version = "1.0.1" @@ -6111,4 +6182,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "6ccbbba60b534e4756d1c36e37ce1379ee2126d37b822f186b5dbb8e8f701ff3" +content-hash = "a20db0b979aa17d15d4669d91dde89ccbfc98bf93406013a1a0946298df2b39b" diff --git a/pyproject.toml b/pyproject.toml index 0869256a9..fcea9f281 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -31,7 +31,7 @@ requests = "^2" # drivers cohere = { version = "^5.5.4", optional = true } -anthropic = { version = "^0.20.0", optional = true } +anthropic = { version = "^0.29.0", optional = true } transformers = { version = "^4.39.3", optional = true } huggingface-hub = { version = ">=0.13", optional = true } boto3 = { version = "^1.34.119", optional = true } diff --git a/tests/unit/config/test_amazon_bedrock_structure_config.py b/tests/unit/config/test_amazon_bedrock_structure_config.py index 33b286f94..44020b815 100644 --- a/tests/unit/config/test_amazon_bedrock_structure_config.py +++ b/tests/unit/config/test_amazon_bedrock_structure_config.py @@ -31,13 +31,13 @@ def test_to_dict(self, config): }, "image_query_driver": { "type": "AmazonBedrockImageQueryDriver", - "model": "anthropic.claude-3-sonnet-20240229-v1:0", + "model": "anthropic.claude-3-5-sonnet-20240620-v1:0", "max_tokens": 256, "image_query_model_driver": {"type": "BedrockClaudeImageQueryModelDriver"}, }, "prompt_driver": { "max_tokens": None, - "model": "anthropic.claude-3-sonnet-20240229-v1:0", + "model": "anthropic.claude-3-5-sonnet-20240620-v1:0", "stream": False, "temperature": 0.1, "type": "AmazonBedrockPromptDriver", diff --git a/tests/unit/config/test_anthropic_structure_config.py b/tests/unit/config/test_anthropic_structure_config.py index 1dd83f96c..03f9775f6 100644 --- a/tests/unit/config/test_anthropic_structure_config.py +++ b/tests/unit/config/test_anthropic_structure_config.py @@ -20,7 +20,7 @@ def test_to_dict(self, config): "temperature": 0.1, "max_tokens": 1000, "stream": False, - "model": "claude-3-opus-20240229", + "model": "claude-3-5-sonnet-20240620", "top_p": 0.999, "top_k": 250, }, From 01e4213daa8c374c614aeb096e3934aec7d11217 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 20 Jun 2024 15:08:24 -0700 Subject: [PATCH 07/87] Version bump v0.27.1 (#887) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fcea9f281..1ed9e0d3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "griptape" -version = "0.27.0" +version = "0.27.1" description = "Modular Python framework for LLM workflows, tools, memory, and data." authors = ["Griptape "] license = "Apache 2.0" From ab82f3c7d5f3b7911e5a4ab1c9b6906e05bda718 Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Fri, 21 Jun 2024 12:25:10 -0500 Subject: [PATCH 08/87] Add `ProxyWebScraperDriver` (#886) --- .github/workflows/docs-integration-tests.yml | 1 + CHANGELOG.md | 1 + .../drivers/web-scraper-drivers.md | 30 ++++++++++++++++ griptape/drivers/__init__.py | 2 ++ .../web_scraper/proxy_web_scraper_driver.py | 17 ++++++++++ .../test_proxy_web_scraper_driver.py | 34 +++++++++++++++++++ 6 files changed, 85 insertions(+) create mode 100644 griptape/drivers/web_scraper/proxy_web_scraper_driver.py create mode 100644 tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index f752aa90d..79e0c9f3a 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -119,6 +119,7 @@ jobs: PUSHER_KEY: ${{ secrets.INTEG_PUSHER_KEY }} PUSHER_SECRET: ${{ secrets.INTEG_PUSHER_SECRET }} PUSHER_CLUSTER: ${{ secrets.INTEG_PUSHER_CLUSTER }} + ZENROWS_API_KEY: ${{ secrets.INTEG_ZENROWS_API_KEY }} services: postgres: image: ankane/pgvector:v0.5.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index 62846b623..6632b97fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `GoogleWebSearchDriver` to web search with the Google Customsearch API. - `DuckDuckGoWebSearchDriver` to web search with the DuckDuckGo search SDK. +- `ProxyWebScraperDriver` to web scrape using proxies. ### Changed - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. diff --git a/docs/griptape-framework/drivers/web-scraper-drivers.md b/docs/griptape-framework/drivers/web-scraper-drivers.md index c6835e1b5..8c05a3df2 100644 --- a/docs/griptape-framework/drivers/web-scraper-drivers.md +++ b/docs/griptape-framework/drivers/web-scraper-drivers.md @@ -6,6 +6,36 @@ Web Scraper Drivers can be used to scrape text from the web. They are used by [W ## Web Scraper Drivers +### Proxy + +The [ProxyWebScraperDriver](../../reference/griptape/drivers/web_scraper/proxy_web_scraper_driver.md) uses the `requests` library with a provided set of proxies to do web scraping. Paid webscraping services like [ZenRows](https://www.zenrows.com/) or [ScraperAPI](https://www.scraperapi.com/) offer a way to use their API via a set of proxies passed to `requests.get()` + +Example using `ProxyWebScraperDriver` directly: + +```python +import os +from griptape.drivers import ProxyWebScraperDriver + +query_params = [ + "markdown_response=true", + "js_render=false", + "premium_proxy=false", +] +proxy_url = f'http://{os.environ["ZENROWS_API_KEY"]}:{"&".join(query_params)}@proxy.zenrows.com:8001' + +driver = ProxyWebScraperDriver( + proxies={ + "http": proxy_url, + "https": proxy_url, + }, + params={ + "verify": False + } +) + +driver.scrape_url("https://griptape.ai") +``` + ### Markdownify !!! info diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 3576b66bb..94198b734 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -73,6 +73,7 @@ from .web_scraper.base_web_scraper_driver import BaseWebScraperDriver from .web_scraper.trafilatura_web_scraper_driver import TrafilaturaWebScraperDriver from .web_scraper.markdownify_web_scraper_driver import MarkdownifyWebScraperDriver +from .web_scraper.proxy_web_scraper_driver import ProxyWebScraperDriver from .web_search.base_web_search_driver import BaseWebSearchDriver from .web_search.google_web_search_driver import GoogleWebSearchDriver @@ -167,6 +168,7 @@ "BaseWebScraperDriver", "TrafilaturaWebScraperDriver", "MarkdownifyWebScraperDriver", + "ProxyWebScraperDriver", "BaseWebSearchDriver", "GoogleWebSearchDriver", "DuckDuckGoWebSearchDriver", diff --git a/griptape/drivers/web_scraper/proxy_web_scraper_driver.py b/griptape/drivers/web_scraper/proxy_web_scraper_driver.py new file mode 100644 index 000000000..4a9213365 --- /dev/null +++ b/griptape/drivers/web_scraper/proxy_web_scraper_driver.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from attrs import field, Factory, define +import requests + +from griptape.artifacts import TextArtifact +from griptape.drivers import BaseWebScraperDriver + + +@define +class ProxyWebScraperDriver(BaseWebScraperDriver): + proxies: dict = field(kw_only=True, metadata={"serializable": False}) + params: dict = field(default=Factory(dict), kw_only=True, metadata={"serializable": True}) + + def scrape_url(self, url: str) -> TextArtifact: + response = requests.get(url, proxies=self.proxies, **self.params) + return TextArtifact(response.text) diff --git a/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py b/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py new file mode 100644 index 000000000..569800c6a --- /dev/null +++ b/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py @@ -0,0 +1,34 @@ +import pytest + +from griptape.drivers import ProxyWebScraperDriver +from griptape.artifacts import TextArtifact + + +class TestProxyWebScraperDriver: + @pytest.fixture(autouse=True) + def mock_client(self, mocker): + mock_response = mocker.Mock() + mock_response.text = "test_scrape" + return mocker.patch("requests.get", return_value=mock_response) + + @pytest.fixture + def mock_client_error(self, mocker): + return mocker.patch("requests.get", side_effect=Exception("test_error")) + + @pytest.fixture + def web_scraper(self, mocker): + return ProxyWebScraperDriver( + proxies={"http": "http://localhost:8080", "https": "http://localhost:8080"}, + params={"test_param": "test_param"}, + ) + + def test_scrape_url(self, web_scraper, mock_client): + output = web_scraper.scrape_url("https://example.com/") + mock_client.assert_called_with("https://example.com/", proxies=web_scraper.proxies, test_param="test_param") + assert isinstance(output, TextArtifact) + assert "test_scrape" == output.value + + def test_scrape_url_error(self, web_scraper, mock_client_error): + with pytest.raises(Exception, match="test_error"): + web_scraper.scrape_url("https://example.com/") + assert mock_client_error.called From cff3f79196971c01e6c06d28fbfb45cdb511b518 Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Fri, 21 Jun 2024 12:40:23 -0500 Subject: [PATCH 09/87] Update `AmazonBedrockStructureConfig` with helper params (#882) --- CHANGELOG.md | 1 + docs/griptape-framework/structures/config.md | 10 +++- .../config/amazon_bedrock_structure_config.py | 55 ++++++++++++----- .../test_amazon_bedrock_structure_config.py | 59 +++++++++++++++++++ 4 files changed, 108 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6632b97fe..683698785 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `GoogleWebSearchDriver` to web search with the Google Customsearch API. - `DuckDuckGoWebSearchDriver` to web search with the DuckDuckGo search SDK. - `ProxyWebScraperDriver` to web scrape using proxies. +- Parameter `session` on `AmazonBedrockStructureConfig`. ### Changed - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. diff --git a/docs/griptape-framework/structures/config.md b/docs/griptape-framework/structures/config.md index d75354768..1a69d70c0 100644 --- a/docs/griptape-framework/structures/config.md +++ b/docs/griptape-framework/structures/config.md @@ -48,11 +48,19 @@ agent = Agent( The [Amazon Bedrock Structure Config](../../reference/griptape/config/amazon_bedrock_structure_config.md) provides default Drivers for Amazon Bedrock's APIs. ```python +import os +import boto3 from griptape.structures import Agent from griptape.config import AmazonBedrockStructureConfig agent = Agent( - config=AmazonBedrockStructureConfig() + config=AmazonBedrockStructureConfig( + session=boto3.Session( + region_name=os.environ["AWS_DEFAULT_REGION"], + aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"], + aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"], + ) + ) ) ``` diff --git a/griptape/config/amazon_bedrock_structure_config.py b/griptape/config/amazon_bedrock_structure_config.py index e70d9c819..3addf3b36 100644 --- a/griptape/config/amazon_bedrock_structure_config.py +++ b/griptape/config/amazon_bedrock_structure_config.py @@ -1,5 +1,9 @@ +from __future__ import annotations +from typing import TYPE_CHECKING from attrs import Factory, define, field +from griptape.drivers import BasePromptDriver +from griptape.utils import import_optional_dependency from griptape.config import StructureConfig from griptape.drivers import ( AmazonBedrockImageGenerationDriver, @@ -8,49 +12,68 @@ AmazonBedrockTitanEmbeddingDriver, BaseEmbeddingDriver, BaseImageGenerationDriver, - BasePromptDriver, BaseVectorStoreDriver, BedrockClaudeImageQueryModelDriver, BedrockTitanImageGenerationModelDriver, LocalVectorStoreDriver, ) +if TYPE_CHECKING: + import boto3 -@define() + +@define class AmazonBedrockStructureConfig(StructureConfig): + session: boto3.Session = field( + default=Factory(lambda: import_optional_dependency("boto3").Session()), + kw_only=True, + metadata={"serializable": False}, + ) + prompt_driver: BasePromptDriver = field( default=Factory( - lambda: AmazonBedrockPromptDriver(model="anthropic.claude-3-sonnet-20240229-v1:0", stream=False) + lambda self: AmazonBedrockPromptDriver( + session=self.session, model="anthropic.claude-3-sonnet-20240229-v1:0" + ), + takes_self=True, ), + kw_only=True, + metadata={"serializable": True}, + ) + embedding_driver: BaseEmbeddingDriver = field( + default=Factory( + lambda self: AmazonBedrockTitanEmbeddingDriver(session=self.session, model="amazon.titan-embed-text-v1"), + takes_self=True, + ), + kw_only=True, metadata={"serializable": True}, ) image_generation_driver: BaseImageGenerationDriver = field( default=Factory( - lambda: AmazonBedrockImageGenerationDriver( + lambda self: AmazonBedrockImageGenerationDriver( + session=self.session, model="amazon.titan-image-generator-v1", image_generation_model_driver=BedrockTitanImageGenerationModelDriver(), - ) + ), + takes_self=True, ), + kw_only=True, metadata={"serializable": True}, ) image_query_driver: BaseImageGenerationDriver = field( default=Factory( - lambda: AmazonBedrockImageQueryDriver( + lambda self: AmazonBedrockImageQueryDriver( + session=self.session, model="anthropic.claude-3-sonnet-20240229-v1:0", image_query_model_driver=BedrockClaudeImageQueryModelDriver(), - ) + ), + takes_self=True, ), - metadata={"serializable": True}, - ) - embedding_driver: BaseEmbeddingDriver = field( - default=Factory(lambda: AmazonBedrockTitanEmbeddingDriver(model="amazon.titan-embed-text-v1")), + kw_only=True, metadata={"serializable": True}, ) vector_store_driver: BaseVectorStoreDriver = field( - default=Factory( - lambda: LocalVectorStoreDriver( - embedding_driver=AmazonBedrockTitanEmbeddingDriver(model="amazon.titan-embed-text-v1") - ) - ), + default=Factory(lambda self: LocalVectorStoreDriver(embedding_driver=self.embedding_driver), takes_self=True), + kw_only=True, metadata={"serializable": True}, ) diff --git a/tests/unit/config/test_amazon_bedrock_structure_config.py b/tests/unit/config/test_amazon_bedrock_structure_config.py index 33b286f94..209c28f26 100644 --- a/tests/unit/config/test_amazon_bedrock_structure_config.py +++ b/tests/unit/config/test_amazon_bedrock_structure_config.py @@ -1,3 +1,4 @@ +import boto3 from pytest import fixture from griptape.config import AmazonBedrockStructureConfig from tests.utils.aws import mock_aws_credentials @@ -10,8 +11,17 @@ def run_before_and_after_tests(self): @fixture def config(self): + mock_aws_credentials() return AmazonBedrockStructureConfig() + @fixture + def config_with_values(self): + return AmazonBedrockStructureConfig( + session=boto3.Session( + aws_access_key_id="testing", aws_secret_access_key="testing", region_name="region-value" + ) + ) + def test_to_dict(self, config): assert config.to_dict() == { "conversation_memory_driver": None, @@ -56,3 +66,52 @@ def test_to_dict(self, config): def test_from_dict(self, config): assert AmazonBedrockStructureConfig.from_dict(config.to_dict()).to_dict() == config.to_dict() + + def test_from_dict_with_values(self, config_with_values): + assert ( + AmazonBedrockStructureConfig.from_dict(config_with_values.to_dict()).to_dict() + == config_with_values.to_dict() + ) + + def test_to_dict_with_values(self, config_with_values): + assert config_with_values.to_dict() == { + "conversation_memory_driver": None, + "embedding_driver": {"model": "amazon.titan-embed-text-v1", "type": "AmazonBedrockTitanEmbeddingDriver"}, + "image_generation_driver": { + "image_generation_model_driver": { + "cfg_scale": 7, + "outpainting_mode": "PRECISE", + "quality": "standard", + "type": "BedrockTitanImageGenerationModelDriver", + }, + "image_height": 512, + "image_width": 512, + "model": "amazon.titan-image-generator-v1", + "seed": None, + "type": "AmazonBedrockImageGenerationDriver", + }, + "image_query_driver": { + "type": "AmazonBedrockImageQueryDriver", + "model": "anthropic.claude-3-sonnet-20240229-v1:0", + "max_tokens": 256, + "image_query_model_driver": {"type": "BedrockClaudeImageQueryModelDriver"}, + }, + "prompt_driver": { + "max_tokens": None, + "model": "anthropic.claude-3-sonnet-20240229-v1:0", + "stream": False, + "temperature": 0.1, + "type": "AmazonBedrockPromptDriver", + }, + "vector_store_driver": { + "embedding_driver": { + "model": "amazon.titan-embed-text-v1", + "type": "AmazonBedrockTitanEmbeddingDriver", + }, + "type": "LocalVectorStoreDriver", + }, + "type": "AmazonBedrockStructureConfig", + "text_to_speech_driver": {"type": "DummyTextToSpeechDriver"}, + "audio_transcription_driver": {"type": "DummyAudioTranscriptionDriver"}, + } + assert config_with_values.session.region_name == "region-value" From 535380cccc49079991ea5a3e692f8cb4f6b772ae Mon Sep 17 00:00:00 2001 From: Vasily Vasinov Date: Fri, 21 Jun 2024 17:44:32 -0600 Subject: [PATCH 10/87] Replace `VectorQueryEngine` with `RagEngine` (#860) ### Added - `RagEngine` is an abstraction for implementing modular RAG pipelines. - `RagContext` is a container object for passing around RAG context. - RAG stages: - `QueryRagStage` for parsing and expanding queries. - `RetrievalRagStage` for retrieving content. - `GenerationRagStage` for augmenting and generating outputs. - RAG modules: - Query: - `RelatedQueryGenerationRagModule` for generating related queries. - Retrieval: - `TextRetrievalRagModule` for retrieving text chunks. - `TextRerankRagModule` for re-ranking retrieved results. - Generation: - `MetadataGenerationRagModule` for appending metadata. - `RulesetsGenerationRagModule` for appending rulesets. - `PromptGenerationRagModule` for generating responses based on retrieved text chunks. - `RagClient` tool for exposing `RagEngines` to LLM agents. - `RagTask` task for including `RagEngines` in any structure. - Rerank drivers: - `CohereRerankDriver` for using the Cohere rerank API. - `utils.execute_futures_list()` for executing a list of futures. - `LocalVectorStoreDriver.persist_file` for persisting vectors and chunks in a text file. - `Entry.to_artifact()` for easy vector store entry conversions into Griptape artifacts. - `BaseVectorStoreDriver.does_entry_exist()` to check if an entry exists in the vector store. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. - **BREAKING**: Removed `VectorQueryEngine` in favor of `RagEngine`. - **BREAKING**: Removed `TextQueryTask` in favor of `RagTask`. - **BREAKING**: `TextArtifactStorage` now requires `vector_store_driver` and `rag_engine` in place of `vector_query_engine`. - **BREAKING**: Moved `load_artifacts()` from `BaseQueryEngine` to `BaseVectorStoreDriver`. - **BREAKING**: Merged `BaseVectorStoreDriver.QueryResult` into `BaseVectorStoreDriver.Entry`. - **BREAKING**: Replaced `query_engine` with `vector_store_driver` in `VectorStoreClient`. --- CHANGELOG.md | 31 +++++ README.md | 2 +- docs/examples/load-query-and-chat-marqo.md | 7 +- docs/examples/multiple-agent-shared-memory.md | 6 +- docs/examples/query-webpage.md | 2 +- docs/examples/talk-to-a-pdf.md | 49 ++++---- docs/examples/talk-to-a-webpage.md | 39 +++--- docs/griptape-framework/data/index.md | 12 +- .../drivers/image-query-drivers.md | 2 +- .../drivers/vector-store-drivers.md | 17 +-- .../engines/image-query-engines.md | 25 ++++ .../engines/query-engines.md | 52 -------- .../griptape-framework/engines/rag-engines.md | 66 ++++++++++ .../structures/task-memory.md | 113 ++++++++++++------ docs/griptape-framework/structures/tasks.md | 74 ++++++------ .../official-tools/rag-client.md | 49 ++++++++ .../official-tools/vector-store-client.md | 23 ++-- griptape/artifacts/media_artifact.py | 2 +- griptape/drivers/__init__.py | 5 + griptape/drivers/prompt/base_prompt_driver.py | 14 +-- .../drivers/prompt/cohere_prompt_driver.py | 12 +- .../query => drivers/rerank}/__init__.py | 0 griptape/drivers/rerank/base_rerank_driver.py | 9 ++ .../drivers/rerank/cohere_rerank_driver.py | 31 +++++ .../azure_mongodb_vector_store_driver.py | 4 +- .../vector/base_vector_store_driver.py | 87 +++++++++----- .../vector/dummy_vector_store_driver.py | 2 +- .../vector/local_vector_store_driver.py | 69 ++++++++--- .../vector/marqo_vector_store_driver.py | 16 ++- .../mongodb_atlas_vector_store_driver.py | 4 +- .../vector/opensearch_vector_store_driver.py | 6 +- .../vector/pgvector_vector_store_driver.py | 4 +- .../vector/pinecone_vector_store_driver.py | 4 +- .../vector/redis_vector_store_driver.py | 9 +- griptape/engines/__init__.py | 4 - griptape/engines/query/base_query_engine.py | 29 ----- griptape/engines/query/vector_query_engine.py | 95 --------------- griptape/engines/rag/__init__.py | 4 + griptape/engines/rag/modules/__init__.py | 29 +++++ .../engines/rag/modules/base_rag_module.py | 18 +++ .../rag/modules/generation}/__init__.py | 0 .../base_after_generation_rag_module.py | 10 ++ .../base_before_generation_rag_module.py | 10 ++ .../generation/base_generation_rag_module.py | 10 ++ .../metadata_generation_rag_module.py | 20 ++++ .../prompt_generation_rag_module.py | 54 +++++++++ .../rulesets_generation_rag_module.py | 15 +++ .../engines/rag/modules/query/__init__.py | 0 .../modules/query/base_query_rag_module.py | 10 ++ .../related_query_generation_rag_module.py | 33 +++++ .../engines/rag/modules/retrieval/__init__.py | 0 .../retrieval/base_rerank_rag_module.py | 16 +++ .../retrieval/base_retrieval_rag_module.py | 12 ++ .../retrieval/text_rerank_rag_module.py | 12 ++ .../retrieval/text_retrieval_rag_module.py | 35 ++++++ griptape/engines/rag/rag_context.py | 29 +++++ griptape/engines/rag/rag_engine.py | 26 ++++ griptape/engines/rag/stages/__init__.py | 6 + griptape/engines/rag/stages/base_rag_stage.py | 12 ++ .../rag/stages/generation_rag_stage.py | 33 +++++ .../engines/rag/stages/query_rag_stage.py | 23 ++++ .../engines/rag/stages/retrieval_rag_stage.py | 49 ++++++++ .../task/storage/text_artifact_storage.py | 36 ++++-- griptape/structures/structure.py | 36 ++++-- griptape/tasks/__init__.py | 4 +- griptape/tasks/rag_task.py | 31 +++++ griptape/tasks/text_query_task.py | 35 ------ .../rag/modules/metadata_generation/system.j2 | 5 + .../rag/modules/prompt_generation/system.j2 | 15 +++ .../rag/modules/query_generation/system.j2 | 3 + griptape/tools/__init__.py | 2 + griptape/tools/rag_client/__init__.py | 0 griptape/tools/rag_client/manifest.yml | 5 + griptape/tools/rag_client/requirements.txt | 0 griptape/tools/rag_client/tool.py | 38 ++++++ griptape/tools/vector_store_client/tool.py | 18 +-- griptape/utils/__init__.py | 2 + griptape/utils/futures.py | 6 + mkdocs.yml | 5 +- poetry.lock | 5 +- pyproject.toml | 2 + ...st_text_query_task.py => test_rag_task.py} | 16 ++- .../test_amazon_bedrock_structure_config.py | 4 +- tests/unit/drivers/rerank/__init__.py | 0 .../rerank/test_cohere_rerank_driver.py | 19 +++ ...r.py => base_local_vector_store_driver.py} | 32 +++-- .../test_azure_mongodb_vector_store_driver.py | 6 +- tests/unit/drivers/vector/test_entry.py | 12 ++ ...est_in_memory_local_vector_store_driver.py | 10 ++ .../test_mongodb_atlas_vector_store_driver.py | 6 +- ...st_persistent_local_vector_store_driver.py | 29 +++++ .../test_pinecone_vector_storage_driver.py | 4 +- .../engines/query/test_vector_query_engine.py | 58 --------- tests/unit/engines/rag/__init__.py | 0 tests/unit/engines/rag/modules/__init__.py | 0 .../rag/modules/generation/__init__.py | 0 .../test_metadata_generation_rag_module.py | 14 +++ .../test_prompt_generation_rag_module.py | 25 ++++ .../test_rulesets_generation_rag_module.py | 10 ++ .../engines/rag/modules/query/__init__.py | 0 ...est_related_query_generation_rag_module.py | 13 ++ .../engines/rag/modules/retrieval/__init__.py | 0 .../retrieval/test_text_rerank_rag_module.py | 20 ++++ .../test_text_retrieval_rag_module.py | 20 ++++ tests/unit/engines/rag/test_rag_engine.py | 30 +++++ tests/unit/memory/tool/test_task_memory.py | 2 +- tests/unit/structures/test_agent.py | 15 ++- tests/unit/structures/test_pipeline.py | 4 +- tests/unit/structures/test_workflow.py | 4 +- tests/unit/tasks/test_rag_task.py | 35 ++++++ tests/unit/tasks/test_text_query_task.py | 48 -------- tests/unit/tasks/test_toolkit_task.py | 16 +-- tests/unit/tools/test_rag_client.py | 13 ++ tests/unit/tools/test_vector_store_client.py | 19 +-- tests/unit/utils/test_futures.py | 9 ++ tests/utils/defaults.py | 22 +++- 116 files changed, 1550 insertions(+), 654 deletions(-) create mode 100644 docs/griptape-framework/engines/image-query-engines.md delete mode 100644 docs/griptape-framework/engines/query-engines.md create mode 100644 docs/griptape-framework/engines/rag-engines.md create mode 100644 docs/griptape-tools/official-tools/rag-client.md rename griptape/{engines/query => drivers/rerank}/__init__.py (100%) create mode 100644 griptape/drivers/rerank/base_rerank_driver.py create mode 100644 griptape/drivers/rerank/cohere_rerank_driver.py delete mode 100644 griptape/engines/query/base_query_engine.py delete mode 100644 griptape/engines/query/vector_query_engine.py create mode 100644 griptape/engines/rag/__init__.py create mode 100644 griptape/engines/rag/modules/__init__.py create mode 100644 griptape/engines/rag/modules/base_rag_module.py rename {tests/unit/engines/query => griptape/engines/rag/modules/generation}/__init__.py (100%) create mode 100644 griptape/engines/rag/modules/generation/base_after_generation_rag_module.py create mode 100644 griptape/engines/rag/modules/generation/base_before_generation_rag_module.py create mode 100644 griptape/engines/rag/modules/generation/base_generation_rag_module.py create mode 100644 griptape/engines/rag/modules/generation/metadata_generation_rag_module.py create mode 100644 griptape/engines/rag/modules/generation/prompt_generation_rag_module.py create mode 100644 griptape/engines/rag/modules/generation/rulesets_generation_rag_module.py create mode 100644 griptape/engines/rag/modules/query/__init__.py create mode 100644 griptape/engines/rag/modules/query/base_query_rag_module.py create mode 100644 griptape/engines/rag/modules/query/related_query_generation_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/__init__.py create mode 100644 griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/text_rerank_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py create mode 100644 griptape/engines/rag/rag_context.py create mode 100644 griptape/engines/rag/rag_engine.py create mode 100644 griptape/engines/rag/stages/__init__.py create mode 100644 griptape/engines/rag/stages/base_rag_stage.py create mode 100644 griptape/engines/rag/stages/generation_rag_stage.py create mode 100644 griptape/engines/rag/stages/query_rag_stage.py create mode 100644 griptape/engines/rag/stages/retrieval_rag_stage.py create mode 100644 griptape/tasks/rag_task.py delete mode 100644 griptape/tasks/text_query_task.py create mode 100644 griptape/templates/engines/rag/modules/metadata_generation/system.j2 create mode 100644 griptape/templates/engines/rag/modules/prompt_generation/system.j2 create mode 100644 griptape/templates/engines/rag/modules/query_generation/system.j2 create mode 100644 griptape/tools/rag_client/__init__.py create mode 100644 griptape/tools/rag_client/manifest.yml create mode 100644 griptape/tools/rag_client/requirements.txt create mode 100644 griptape/tools/rag_client/tool.py rename tests/integration/tasks/{test_text_query_task.py => test_rag_task.py} (65%) create mode 100644 tests/unit/drivers/rerank/__init__.py create mode 100644 tests/unit/drivers/rerank/test_cohere_rerank_driver.py rename tests/unit/drivers/vector/{test_local_vector_store_driver.py => base_local_vector_store_driver.py} (62%) create mode 100644 tests/unit/drivers/vector/test_entry.py create mode 100644 tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py create mode 100644 tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py delete mode 100644 tests/unit/engines/query/test_vector_query_engine.py create mode 100644 tests/unit/engines/rag/__init__.py create mode 100644 tests/unit/engines/rag/modules/__init__.py create mode 100644 tests/unit/engines/rag/modules/generation/__init__.py create mode 100644 tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_prompt_generation_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py create mode 100644 tests/unit/engines/rag/modules/query/__init__.py create mode 100644 tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py create mode 100644 tests/unit/engines/rag/modules/retrieval/__init__.py create mode 100644 tests/unit/engines/rag/modules/retrieval/test_text_rerank_rag_module.py create mode 100644 tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py create mode 100644 tests/unit/engines/rag/test_rag_engine.py create mode 100644 tests/unit/tasks/test_rag_task.py delete mode 100644 tests/unit/tasks/test_text_query_task.py create mode 100644 tests/unit/tools/test_rag_client.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 66104a6e1..e920f5a5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,12 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added +- `RagEngine` is an abstraction for implementing modular RAG pipelines. + - `RagContext` is a container object for passing around RAG context. + - RAG stages: + - `QueryRagStage` for parsing and expanding queries. + - `RetrievalRagStage` for retrieving content. + - `GenerationRagStage` for augmenting and generating outputs. + - RAG modules: + - Query: + - `RelatedQueryGenerationRagModule` for generating related queries. + - Retrieval: + - `TextRetrievalRagModule` for retrieving text chunks. + - `TextRerankRagModule` for re-ranking retrieved results. + - Generation: + - `MetadataGenerationRagModule` for appending metadata. + - `RulesetsGenerationRagModule` for appending rulesets. + - `PromptGenerationRagModule` for generating responses based on retrieved text chunks. +- `RagClient` tool for exposing `RagEngines` to LLM agents. +- `RagTask` task for including `RagEngines` in any structure. +- Rerank drivers: + - `CohereRerankDriver` for using the Cohere rerank API. +- `utils.execute_futures_list()` for executing a list of futures. +- `LocalVectorStoreDriver.persist_file` for persisting vectors and chunks in a text file. +- `Entry.to_artifact()` for easy vector store entry conversions into Griptape artifacts. +- `BaseVectorStoreDriver.does_entry_exist()` to check if an entry exists in the vector store. - `GoogleWebSearchDriver` to web search with the Google Customsearch API. - `DuckDuckGoWebSearchDriver` to web search with the DuckDuckGo search SDK. - `ProxyWebScraperDriver` to web scrape using proxies. - Parameter `session` on `AmazonBedrockStructureConfig`. ### Changed +- **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. +- **BREAKING**: Removed `VectorQueryEngine` in favor of `RagEngine`. +- **BREAKING**: Removed `TextQueryTask` in favor of `RagTask`. +- **BREAKING**: `TextArtifactStorage` now requires `vector_store_driver` and `rag_engine` in place of `vector_query_engine`. +- **BREAKING**: Moved `load_artifacts()` from `BaseQueryEngine` to `BaseVectorStoreDriver`. +- **BREAKING**: Merged `BaseVectorStoreDriver.QueryResult` into `BaseVectorStoreDriver.Entry`. +- **BREAKING**: Replaced `query_engine` with `vector_store_driver` in `VectorStoreClient`. - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. ## [0.27.1] - 2024-06-20 diff --git a/README.md b/README.md index b5e4f7bcb..f9eb2aa5c 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ Drivers facilitate interactions with external resources and services: Engines wrap Drivers and provide use-case-specific functionality: -- 📊 **Query Engines** execute Retrieval Augmented Generation (RAG) queries. +- 📊 **RAG Engine** is an abstraction for implementing modular Retrieval Augmented Generation (RAG) pipelines. - 🛠️ **Extraction Engines** extract JSON or CSV data from unstructured text. - 📝 **Summary Engines** generate summaries from textual content. - 🖼️ **Image Generation Engines** generate images from textual descriptions. diff --git a/docs/examples/load-query-and-chat-marqo.md b/docs/examples/load-query-and-chat-marqo.md index 718b42729..fb5906e9e 100644 --- a/docs/examples/load-query-and-chat-marqo.md +++ b/docs/examples/load-query-and-chat-marqo.md @@ -2,11 +2,10 @@ import os from griptape import utils from griptape.drivers import MarqoVectorStoreDriver -from griptape.engines import VectorQueryEngine from griptape.loaders import WebLoader from griptape.structures import Agent from griptape.tools import VectorStoreClient -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.drivers import OpenAiEmbeddingDriver # Define the namespace namespace = "griptape-ai" @@ -18,14 +17,12 @@ vector_store = MarqoVectorStoreDriver( index=os.environ["MARQO_INDEX_NAME"], embedding_driver=OpenAiEmbeddingDriver() ) -# Initialize the query engine -query_engine = VectorQueryEngine(vector_store_driver=vector_store, prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo")) # Initialize the knowledge base tool vector_store_tool = VectorStoreClient( description="Contains information about the Griptape Framework from www.griptape.ai", - query_engine=query_engine, namespace=namespace, + vector_store_driver=vector_store ) # Load artifacts from the web diff --git a/docs/examples/multiple-agent-shared-memory.md b/docs/examples/multiple-agent-shared-memory.md index cc5498d7e..109394d49 100644 --- a/docs/examples/multiple-agent-shared-memory.md +++ b/docs/examples/multiple-agent-shared-memory.md @@ -8,13 +8,9 @@ The `MongoDbAtlasVectorStoreDriver` assumes that you have a vector index configu ```python import os -from griptape.tools import WebScraper, VectorStoreClient, TaskMemoryClient +from griptape.tools import WebScraper, TaskMemoryClient from griptape.structures import Agent from griptape.drivers import AzureOpenAiEmbeddingDriver, AzureMongoDbVectorStoreDriver -from griptape.engines import VectorQueryEngine, PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine -from griptape.memory import TaskMemory -from griptape.artifacts import TextArtifact -from griptape.memory.task.storage import TextArtifactStorage from griptape.config import AzureOpenAiStructureConfig diff --git a/docs/examples/query-webpage.md b/docs/examples/query-webpage.md index d11c5d9c4..07801b32c 100644 --- a/docs/examples/query-webpage.md +++ b/docs/examples/query-webpage.md @@ -22,7 +22,7 @@ results = vector_store.query( namespace="griptape" ) -values = [BaseArtifact.from_json(r.meta["artifact"]).value for r in results] +values = [r.to_artifact().value for r in results] print("\n\n".join(values)) ``` \ No newline at end of file diff --git a/docs/examples/talk-to-a-pdf.md b/docs/examples/talk-to-a-pdf.md index 51f71b4f6..a39832961 100644 --- a/docs/examples/talk-to-a-pdf.md +++ b/docs/examples/talk-to-a-pdf.md @@ -1,48 +1,53 @@ This example demonstrates how to vectorize a PDF of the [Attention Is All You Need](https://arxiv.org/pdf/1706.03762.pdf) paper and setup a Griptape agent with rules and the [VectorStoreClient](../reference/griptape/tools/vector_store_client/tool.md) tool to use it during conversations. ```python -import os -import io import requests -from griptape.engines import VectorQueryEngine +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage from griptape.loaders import PdfLoader from griptape.structures import Agent -from griptape.tools import VectorStoreClient +from griptape.tools import RagClient from griptape.utils import Chat -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver - namespace = "attention" - response = requests.get("https://arxiv.org/pdf/1706.03762.pdf") - -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver( - model="gpt-3.5-turbo", +vector_store = LocalVectorStoreDriver( + embedding_driver=OpenAiEmbeddingDriver() +) +engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + TextRetrievalRagModule( + namespace=namespace, + vector_store_driver=vector_store, + top_n=20 + ) + ] ), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=OpenAiEmbeddingDriver( - api_key=os.environ["OPENAI_API_KEY"] + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) ) +vector_store_tool = RagClient( + description="Contains information about the Attention Is All You Need paper. " + "Use it to answer any related questions.", + rag_engine=engine +) -engine.vector_store_driver.upsert_text_artifacts( +vector_store.upsert_text_artifacts( { namespace: PdfLoader().load(response.content) } ) -vector_store_tool = VectorStoreClient( - description="Contains information about the Attention Is All You Need paper. " - "Use it to answer any related questions.", - query_engine=engine, - namespace=namespace, -) - agent = Agent( tools=[vector_store_tool] ) Chat(agent).start() + ``` diff --git a/docs/examples/talk-to-a-webpage.md b/docs/examples/talk-to-a-webpage.md index 2f2cbf209..ddd1a18c9 100644 --- a/docs/examples/talk-to-a-webpage.md +++ b/docs/examples/talk-to-a-webpage.md @@ -1,25 +1,33 @@ -This example demonstrates how to vectorize a webpage and setup a Griptape agent with rules and the [VectorStoreClient](../reference/griptape/tools/vector_store_client/tool.md) tool to use it during conversations. +This example demonstrates how to vectorize a webpage and setup a Griptape agent with rules and the [RagClient](../reference/griptape/tools/rag_client/tool.md) tool to use it during conversations. ```python -import os -from griptape.engines import VectorQueryEngine +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage from griptape.loaders import WebLoader from griptape.rules import Ruleset, Rule from griptape.structures import Agent -from griptape.tools import VectorStoreClient +from griptape.tools import RagClient from griptape.utils import Chat -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver - namespace = "physics-wiki" -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver( - model="gpt-3.5-turbo", +vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + +engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + TextRetrievalRagModule( + namespace=namespace, + vector_store_driver=vector_store_driver, + top_n=20 + ) + ] ), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=OpenAiEmbeddingDriver( - api_key=os.environ["OPENAI_API_KEY"] + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) ) @@ -28,16 +36,15 @@ artifacts = WebLoader().load( "https://en.wikipedia.org/wiki/Physics" ) -engine.vector_store_driver.upsert_text_artifacts( +vector_store_driver.upsert_text_artifacts( {namespace: artifacts} ) -vector_store_tool = VectorStoreClient( +vector_store_tool = RagClient( description="Contains information about physics. " "Use it to answer any physics-related questions.", - query_engine=engine, - namespace=namespace, + rag_engine=engine ) agent = Agent( diff --git a/docs/griptape-framework/data/index.md b/docs/griptape-framework/data/index.md index 73dfe4c66..3e4359737 100644 --- a/docs/griptape-framework/data/index.md +++ b/docs/griptape-framework/data/index.md @@ -14,7 +14,17 @@ Griptape provides several abstractions for working with data. **Tokenizers** are used to tokenize and detokenize text in order to track LLM token limits. -[Query Engines](../engines/query-engines.md) are used to search text storages. +[Audio Engines](../engines/audio-engines.md) are used for working with audio. + +[Extraction Engines](../engines/extraction-engines.md) are used for extracting structured content. + +[Image Query Engines](../engines/image-query-engines.md) are used for querying images with text. + +[Image Generation Engines](../engines/image-generation-engines.md) are used for generating images. + +[Summary Engines](../engines/summary-engines.md) are used for summarizing text content. + +[RAG Engines](../engines/rag-engines.md) are used for implementing modular RAG pipelines. [Vector Store Drivers](../drivers/vector-store-drivers.md) are used to store and query vector databases. diff --git a/docs/griptape-framework/drivers/image-query-drivers.md b/docs/griptape-framework/drivers/image-query-drivers.md index 720aa1819..6fde89b80 100644 --- a/docs/griptape-framework/drivers/image-query-drivers.md +++ b/docs/griptape-framework/drivers/image-query-drivers.md @@ -1,6 +1,6 @@ ## Overview -Image Query Drivers are used by [Image Query Engines](../engines/query-engines.md#image) to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular Image Query Driver. +Image Query Drivers are used by [Image Query Engines](../engines/image-query-engines.md) to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular Image Query Driver. !!! info All Image Query Drivers default to a `max_tokens` of 256. It is recommended that you set this value to correspond to the desired response length. diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 96480527a..095c14f22 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -43,7 +43,7 @@ results = vector_store_driver.query( namespace="griptape" ) -values = [BaseArtifact.from_json(r.meta["artifact"]).value for r in results] +values = [r.to_artifact().value for r in results] print("\n\n".join(values)) @@ -117,9 +117,7 @@ Here is an example of how the driver can be used to load and query information i ```python import os from griptape.drivers import MarqoVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver -from griptape.engines import VectorQueryEngine from griptape.loaders import WebLoader -from griptape.tools import VectorStoreClient # Initialize an embedding driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) @@ -136,25 +134,16 @@ vector_store = MarqoVectorStoreDriver( embedding_driver=embedding_driver, ) -# Initialize the query engine -query_engine = VectorQueryEngine(vector_store_driver=vector_store, prompt_driver=prompt_driver) - -# Initialize the knowledge base tool -VectorStoreClient( - description="Contains information about the Griptape Framework from www.griptape.ai", - query_engine=query_engine, - namespace=namespace, -) - # Load artifacts from the web artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") # Upsert the artifacts into the vector store vector_store.upsert_text_artifacts( { - namespace: artifacts, + "griptape": artifacts, } ) + result = vector_store.query(query="What is griptape?") print(result) ``` diff --git a/docs/griptape-framework/engines/image-query-engines.md b/docs/griptape-framework/engines/image-query-engines.md new file mode 100644 index 000000000..def6cbd5d --- /dev/null +++ b/docs/griptape-framework/engines/image-query-engines.md @@ -0,0 +1,25 @@ +## Image Query Engines + +The [Image Query Engine](../../reference/griptape/engines/image_query/image_query_engine.md) allows you to perform natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular [Image Query Driver](../drivers/image-query-drivers.md). + +All Image Query Drivers default to a `max_tokens` of 256. You can tune this value based on your use case and the [Image Query Driver](../drivers/image-query-drivers.md) you are providing. + +```python +from griptape.drivers import OpenAiImageQueryDriver +from griptape.engines import ImageQueryEngine +from griptape.loaders import ImageLoader + +driver = OpenAiImageQueryDriver( + model="gpt-4o", + max_tokens=256 +) + +engine = ImageQueryEngine( + image_query_driver=driver +) + +with open("tests/resources/mountain.png", "rb") as f: + image_artifact = ImageLoader().load(f.read()) + +engine.run("Describe the weather in the image", [image_artifact]) +``` diff --git a/docs/griptape-framework/engines/query-engines.md b/docs/griptape-framework/engines/query-engines.md deleted file mode 100644 index 38f5f6610..000000000 --- a/docs/griptape-framework/engines/query-engines.md +++ /dev/null @@ -1,52 +0,0 @@ -## Overview -Query engines are used to perform text queries against various modalities. - -## Vector - -Used to query vector storages. You can set a custom [prompt_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.prompt_driver) and [vector_store_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.vector_store_driver). Uses [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) by default. - -Use the [upsert_text_artifact](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.upsert_text_artifact)s into vector storage with an optional `namespace`. - -Use the [VectorQueryEngine](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.query) method to query the vector storage. - -```python -from griptape.drivers import OpenAiChatPromptDriver, LocalVectorStoreDriver, OpenAiEmbeddingDriver -from griptape.engines import VectorQueryEngine -from griptape.loaders import WebLoader - -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo"), - vector_store_driver=LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) -) - -engine.upsert_text_artifacts( - WebLoader().load("https://www.griptape.ai"), namespace="griptape" -) - -engine.query("what is griptape?", namespace="griptape") -``` - -## Image -The [Image Query Engine](../../reference/griptape/engines/image_query/image_query_engine.md) allows you to perform natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular [Image Query Driver](../drivers/image-query-drivers.md). - -All Image Query Drivers default to a `max_tokens` of 256. You can tune this value based on your use case and the [Image Query Driver](../drivers/image-query-drivers.md) you are providing. - -```python -from griptape.drivers import OpenAiImageQueryDriver -from griptape.engines import ImageQueryEngine -from griptape.loaders import ImageLoader - -driver = OpenAiImageQueryDriver( - model="gpt-4o", - max_tokens=256 -) - -engine = ImageQueryEngine( - image_query_driver=driver -) - -with open("tests/resources/mountain.png", "rb") as f: - image_artifact = ImageLoader().load(f.read()) - -engine.run("Describe the weather in the image", [image_artifact]) -``` diff --git a/docs/griptape-framework/engines/rag-engines.md b/docs/griptape-framework/engines/rag-engines.md new file mode 100644 index 000000000..600b91d03 --- /dev/null +++ b/docs/griptape-framework/engines/rag-engines.md @@ -0,0 +1,66 @@ +## RAG Engines + +!!! note + This section is a work in progress. + +`RagEngine` is an abstraction for implementing modular RAG pipelines. + +`RagContext` is a container object for passing around RAG context. + +### RAG Stages +- `QueryRagStage` is for parsing and expanding queries. +- `RetrievalRagStage` is for retrieving content. +- `GenerationRagStage` is for augmenting and generating outputs. + +### RAG Modules + +#### Query +- `RelatedQueryGenerationRagModule` is for generating related queries. + +#### Retrieval +- `TextRetrievalRagModule` is for retrieving text chunks. +- `TextRerankRagModule` is for re-ranking retrieved results. + +#### Generation +- `MetadataGenerationRagModule` is for appending metadata. +- `RulesetsGenerationRagModule` is for appending rulesets. +- `PromptGenerationRagModule` is for generating responses based on retrieved text chunks. + +### Example + +```python +from griptape.artifacts import TextArtifact +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage + +vector_store = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + +artifacts = [ + TextArtifact("Griptape builds AI-powered applications that connect securely to your enterprise data and APIs."), + TextArtifact("Griptape Agents provide incredible power and flexibility when working with large language models.") +] +vector_store.upsert_text_artifacts({"griptape": artifacts}) + +engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + TextRetrievalRagModule( + namespace="griptape", + vector_store_driver=vector_store, + top_n=20 + ) + ] + ), + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) +) + +print( + engine.process_query("what are Griptape agents?").output.to_text() +) +``` \ No newline at end of file diff --git a/docs/griptape-framework/structures/task-memory.md b/docs/griptape-framework/structures/task-memory.md index 219fd4412..4597b6402 100644 --- a/docs/griptape-framework/structures/task-memory.md +++ b/docs/griptape-framework/structures/task-memory.md @@ -198,24 +198,26 @@ Because Task Memory splits up the storage and retrieval of data, you can use dif Here is an example where we use GPT-4 to orchestrate the Tools and store the data in Task Memory, and Amazon Bedrock's Titan model to query the raw content. In this example, GPT-4 _never_ sees the contents of the page, only that it was stored in Task Memory. Even the query results generated by the Titan model are stored in Task Memory so that the `FileManager` can save the results to disk without GPT-4 ever seeing them. - ```python from griptape.artifacts import TextArtifact from griptape.config import ( OpenAiStructureConfig, ) from griptape.drivers import ( - AmazonBedrockPromptDriver, - AmazonBedrockTitanEmbeddingDriver, LocalVectorStoreDriver, - OpenAiChatPromptDriver, + OpenAiChatPromptDriver, OpenAiEmbeddingDriver, ) -from griptape.engines import VectorQueryEngine +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage from griptape.memory import TaskMemory from griptape.memory.task.storage import TextArtifactStorage from griptape.structures import Agent from griptape.tools import FileManager, TaskMemoryClient, WebScraper + +vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + agent = Agent( config=OpenAiStructureConfig( prompt_driver=OpenAiChatPromptDriver(model="gpt-4"), @@ -223,21 +225,30 @@ agent = Agent( task_memory=TaskMemory( artifact_storages={ TextArtifact: TextArtifactStorage( - query_engine=VectorQueryEngine( - prompt_driver=AmazonBedrockPromptDriver( - model="amazon.titan-text-express-v1", - ), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=AmazonBedrockTitanEmbeddingDriver() + rag_engine=RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + TextRetrievalRagModule( + namespace="griptape", + vector_store_driver=vector_store_driver, + top_n=20 + ) + ] ), + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) ), - ), + vector_store_driver=vector_store_driver + ) } ), tools=[ WebScraper(off_prompt=True), TaskMemoryClient(off_prompt=True, allowlist=["query"]), - FileManager(off_prompt=True), # FileManager returns an InfoArtifact which will not be stored in Task Memory regardless of the off_prompt setting + FileManager(off_prompt=True), ], ) @@ -247,27 +258,61 @@ agent.run( ``` ``` -[04/30/24 16:36:45] INFO ToolkitTask 3d3c5f5a98a44f32ad9533621c036604 - Input: According to this page https://en.wikipedia.org/wiki/Elden_Ring, find how many copies of Elden Ring have been sold and then save the - result to a file. -[04/30/24 16:36:52] INFO Subtask 61ec822bfe49472c9ed874fad07d13a1 - Thought: First, I need to scrape the content of the provided URL. Then, I will search the scraped content for the number of copies of Elden Ring that have been sold. Finally, I will save this information to a file. - - Actions: [{"name": "WebScraper", "path": "get_content", "input": {"values": {"url": "https://en.wikipedia.org/wiki/Elden_Ring"}}, "tag": "scrape_elden_ring"}] -[04/30/24 16:37:04] INFO Subtask 61ec822bfe49472c9ed874fad07d13a1 - Response: Output of "WebScraper.get_content" was stored in memory with memory_name "TaskMemory" and artifact_namespace "c7a01e8202e24869b7be559e0daff110" -[04/30/24 16:37:10] INFO Subtask 32f9cb73d8944e5ca36bd68a90e4f4b2 - Thought: Now that the webpage content is stored in memory, I need to query this memory to find the number of copies of Elden Ring that have been sold. - Actions: [{"tag": "query_sales", "name": "TaskMemoryClient", "path": "query", "input": {"values": {"memory_name": "TaskMemory", "artifact_namespace": "c7a01e8202e24869b7be559e0daff110", "query": "How many copies of Elden Ring have been sold?"}}}] -[04/30/24 16:37:18] INFO Subtask 32f9cb73d8944e5ca36bd68a90e4f4b2 - Response: Output of "TaskMemoryClient.query" was stored in memory with memory_name "TaskMemory" and artifact_namespace "f8dd40fb302a47d7862c8b76eeaf61c2" -[04/30/24 16:37:25] INFO Subtask 74a5fd392b044956842a56b76d09183e - Thought: Now that I have the number of copies sold stored in memory, I need to save this information to a file. - Actions: [{"tag": "save_sales", "name": "FileManager", "path": "save_memory_artifacts_to_disk", "input": {"values": {"dir_name": "sales_data", "file_name": "elden_ring_sales.txt", "memory_name": "TaskMemory", "artifact_namespace": "f8dd40fb302a47d7862c8b76eeaf61c2"}}}] - INFO Subtask 74a5fd392b044956842a56b76d09183e - Response: Successfully saved memory artifacts to disk -[04/30/24 16:37:27] INFO ToolkitTask 3d3c5f5a98a44f32ad9533621c036604 - Output: The number of copies of Elden Ring sold has been successfully saved to the file "elden_ring_sales.txt" in the "sales_data" directory. +[06/21/24 16:00:01] INFO ToolkitTask 17f30ac14701490c8ef71508f420ea9f + Input: Use this page + https://en.wikipedia.org/wiki/Elden_Ring to find + how many copies of Elden Ring have been sold, and + then save the result to a file. +[06/21/24 16:00:05] INFO Subtask cb06889205334ec9afd7e97f7f231ab5 + Thought: First, I need to scrape the content of the + provided URL to find the information about how many + copies of Elden Ring have been sold. Then, I will + save this information to a file. + + Actions: [{"name": "WebScraper", "path": + "get_content", "input": {"values": {"url": + "https://en.wikipedia.org/wiki/Elden_Ring"}}, + "tag": "scrape_elden_ring"}] +[06/21/24 16:00:12] INFO Subtask cb06889205334ec9afd7e97f7f231ab5 + Response: Output of "WebScraper.get_content" was + stored in memory with memory_name "TaskMemory" and + artifact_namespace + "7e48bcff0da94ad3b06aa4e173f8f37b" +[06/21/24 16:00:17] INFO Subtask 56102d42475d413299ce52a0230506b7 + Thought: Now that the webpage content is stored in + memory, I need to query this memory to find the + information about how many copies of Elden Ring + have been sold. + Actions: [{"tag": "query_sales", "name": + "TaskMemoryClient", "path": "query", "input": + {"values": {"memory_name": "TaskMemory", + "artifact_namespace": + "7e48bcff0da94ad3b06aa4e173f8f37b", "query": "How + many copies of Elden Ring have been sold?"}}}] +[06/21/24 16:00:19] INFO Subtask 56102d42475d413299ce52a0230506b7 + Response: Output of "TaskMemoryClient.query" was + stored in memory with memory_name "TaskMemory" and + artifact_namespace + "9ecf4d7b7d0c46149dfc46ba236f178e" +[06/21/24 16:00:25] INFO Subtask ed2921791dcf46b68c9d8d2f8dbeddbd + Thought: Now that I have the sales information + stored in memory, I need to save this information + to a file. + Actions: [{"tag": "save_sales_info", "name": + "FileManager", "path": + "save_memory_artifacts_to_disk", "input": + {"values": {"dir_name": "sales_info", "file_name": + "elden_ring_sales.txt", "memory_name": + "TaskMemory", "artifact_namespace": + "9ecf4d7b7d0c46149dfc46ba236f178e"}}}] + INFO Subtask ed2921791dcf46b68c9d8d2f8dbeddbd + Response: Successfully saved memory artifacts to + disk +[06/21/24 16:00:27] INFO ToolkitTask 17f30ac14701490c8ef71508f420ea9f + Output: The information about how many copies of + Elden Ring have been sold has been successfully + saved to the file "elden_ring_sales.txt" in the + "sales_info" directory. ``` ## Tools That Can Read From Task Memory diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index c43603b1b..6bb517fa2 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -72,7 +72,7 @@ from griptape.structures import Agent agent = Agent() agent.add_task( # take the first argument from the agent `run` method - PromptTask("Respond to the users following request: {{ args[0] }}"), + PromptTask("Respond to the following request: {{ args[0] }}"), ) agent.run("Write me a haiku") @@ -80,7 +80,7 @@ agent.run("Write me a haiku") ``` [10/20/23 15:27:26] INFO PromptTask f5025c6352914e9f80ef730e5269985a - Input: Respond to the users following request: + Input: Respond to the following request: Write me a haiku [10/20/23 15:27:28] INFO PromptTask f5025c6352914e9f80ef730e5269985a Output: Gentle morning dew, @@ -350,40 +350,50 @@ agent.run( senses, bringing a revolution in technology. ``` -## Text Query Task +## RAG Task -To query text, use the [TextQueryTask](../../reference/griptape/tasks/text_query_task.md). -This Task takes a [Query Engine](../../griptape-framework/engines/query-engines.md), and a set of arguments specific to the engine. +To query text, use the [RagTask](../../reference/griptape/tasks/rag_task.md). +This task takes a [RAG Engine](../../griptape-framework/engines/rag-engines.md), and a set of arguments specific to the engine. ```python -from griptape.drivers import OpenAiChatPromptDriver from griptape.structures import Agent -from griptape.tasks import TextQueryTask -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver -from griptape.engines import VectorQueryEngine +from griptape.tasks import RagTask +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage # Initialize Embedding Driver and Vector Store Driver vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) -artifact = TextArtifact( - "Griptape builds AI-powered applications that connect securely to your enterprise data and APIs." - "Griptape Agents provide incredible power and flexibility when working with large language models." -) - -# Create a VectorQueryEngine using the LocalVectorStoreDriver -vector_query_engine = VectorQueryEngine( - vector_store_driver=vector_store_driver, - prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo") -) -vector_query_engine.upsert_text_artifact(artifact=artifact) +artifacts = [ + TextArtifact("Griptape builds AI-powered applications that connect securely to your enterprise data and APIs."), + TextArtifact("Griptape Agents provide incredible power and flexibility when working with large language models.") +] +vector_store_driver.upsert_text_artifacts({"griptape": artifacts}) -# Instantiate the agent and add TextQueryTask with the VectorQueryEngine +# Instantiate the agent and add RagTask with the RagEngine agent = Agent() agent.add_task( - TextQueryTask( - "Respond to the users following query: {{ args[0] }}", - query_engine=vector_query_engine, + RagTask( + "Respond to the following query: {{ args[0] }}", + rag_engine=RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + TextRetrievalRagModule( + namespace="griptape", + vector_store_driver=vector_store_driver, + top_n=20 + ) + ] + ), + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) + ), ) ) @@ -391,21 +401,9 @@ agent.add_task( agent.run("Give me information about Griptape") ``` -``` -[10/20/23 15:32:39] INFO TextQueryTask a1d2eceab9204679b3f701f6ea821606 - Input: Respond to the users following query: Give - me information about Griptape -[10/20/23 15:32:41] INFO TextQueryTask a1d2eceab9204679b3f701f6ea821606 - Output: Griptape builds AI-powered applications - that connect securely to your enterprise data and - APIs. Griptape Agents provide incredible power and - flexibility when working with large language - models. -``` - ## Code Execution Task -To execute an arbitrary Python function, use the [CodeExecutionTask](../../reference/griptape/tasks/text_query_task.md). +To execute an arbitrary Python function, use the [CodeExecutionTask](../../reference/griptape/tasks/code_execution_task.md). This task takes a python function, and authors can elect to return a custom artifact. ```python @@ -627,7 +625,7 @@ pipeline.run("An image of a mountain shrouded by clouds") ## Image Query Task -The [Image Query Task](../../reference/griptape/tasks/image_query_task.md) performs a natural language query on one or more input images. This Task uses an [Image Query Engine](../engines/query-engines.md#image) configured with an [Image Query Driver](../drivers/image-query-drivers.md) to perform the query. The functionality provided by this Task depend on the capabilities of the model provided by the Driver. +The [Image Query Task](../../reference/griptape/tasks/image_query_task.md) performs a natural language query on one or more input images. This Task uses an [Image Query Engine](../engines/image-query-engines.md) configured with an [Image Query Driver](../drivers/image-query-drivers.md) to perform the query. The functionality provided by this Task depend on the capabilities of the model provided by the Driver. This Task accepts two inputs: a query (represented by either a string or a [Text Artifact](../data/artifacts.md#textartifact)) and a list of [Image Artifacts](../data/artifacts.md#imageartifact) or a Callable returning these two values. diff --git a/docs/griptape-tools/official-tools/rag-client.md b/docs/griptape-tools/official-tools/rag-client.md new file mode 100644 index 000000000..75bc5dee7 --- /dev/null +++ b/docs/griptape-tools/official-tools/rag-client.md @@ -0,0 +1,49 @@ +The [RagClient](../../reference/griptape/tools/rag_client/tool.md) enables LLMs to query modular RAG engines. + +Here is an example of how it can be used with a local vector store driver: + +```python +from griptape.structures import Agent +from griptape.tasks import RagTask +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage + +# Initialize Embedding Driver and Vector Store Driver +vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + +artifact = TextArtifact( + "Griptape builds AI-powered applications that connect securely to your enterprise data and APIs." + "Griptape Agents provide incredible power and flexibility when working with large language models." +) +vector_store_driver.upsert_text_artifact(artifact=artifact, namespace="griptape") + +# Instantiate the agent and add RagTask with the RagEngine +agent = Agent() +agent.add_task( + RagTask( + "Respond to the following query: {{ args[0] }}", + rag_engine=RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + TextRetrievalRagModule( + namespace="griptape", + vector_store_driver=vector_store_driver, + top_n=20 + ) + ] + ), + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) + ), + ) +) + +# Run the agent with a query string +agent.run("Give me information about Griptape") +``` diff --git a/docs/griptape-tools/official-tools/vector-store-client.md b/docs/griptape-tools/official-tools/vector-store-client.md index 5af8cee88..ffdbbba91 100644 --- a/docs/griptape-tools/official-tools/vector-store-client.md +++ b/docs/griptape-tools/official-tools/vector-store-client.md @@ -1,29 +1,26 @@ -The [VectorStoreClient](../../reference/griptape/tools/vector_store_client/tool.md) enables LLMs to dynamically query task memory. +The [VectorStoreClient](../../reference/griptape/tools/vector_store_client/tool.md) enables LLMs to query vector stores. -Here is an example of how it can be used with the Pincone storage driver: +Here is an example of how it can be used with a local vector store driver: ```python from griptape.structures import Agent from griptape.tools import VectorStoreClient, TaskMemoryClient from griptape.loaders import WebLoader -from griptape.engines import VectorQueryEngine -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo"), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=OpenAiEmbeddingDriver(), - ), +vector_store_driver = LocalVectorStoreDriver( + embedding_driver=OpenAiEmbeddingDriver(), ) -engine.upsert_text_artifacts( - WebLoader().load("https://www.griptape.ai"), - namespace="griptape" +vector_store_driver.upsert_text_artifacts( + { + "griptape": WebLoader().load("https://www.griptape.ai") + } ) vector_db = VectorStoreClient( description="This DB has information about the Griptape Python framework", - query_engine=engine, + vector_store_driver=vector_store_driver, namespace="griptape", off_prompt=True ) diff --git a/griptape/artifacts/media_artifact.py b/griptape/artifacts/media_artifact.py index 92cc0d9cd..2848ec1bb 100644 --- a/griptape/artifacts/media_artifact.py +++ b/griptape/artifacts/media_artifact.py @@ -29,7 +29,7 @@ class MediaArtifact(BlobArtifact): model: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) prompt: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) - def __attrs_post_init__(self): + def __attrs_post_init__(self) -> None: # Generating the name string requires attributes set by child classes. # This waits until all attributes are available before generating a name. if self.name == self.id: diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 94198b734..34b43103b 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -90,6 +90,9 @@ from .file_manager.local_file_manager_driver import LocalFileManagerDriver from .file_manager.amazon_s3_file_manager_driver import AmazonS3FileManagerDriver +from .rerank.base_rerank_driver import BaseRerankDriver +from .rerank.cohere_rerank_driver import CohereRerankDriver + from .text_to_speech.base_text_to_speech_driver import BaseTextToSpeechDriver from .text_to_speech.dummy_text_to_speech_driver import DummyTextToSpeechDriver from .text_to_speech.elevenlabs_text_to_speech_driver import ElevenLabsTextToSpeechDriver @@ -181,6 +184,8 @@ "BaseFileManagerDriver", "LocalFileManagerDriver", "AmazonS3FileManagerDriver", + "BaseRerankDriver", + "CohereRerankDriver", "BaseTextToSpeechDriver", "DummyTextToSpeechDriver", "ElevenLabsTextToSpeechDriver", diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 9ef076dbc..45f95d544 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -14,7 +14,7 @@ from griptape.structures import Structure -@define +@define(kw_only=True) class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): """Base class for Prompt Drivers. @@ -29,15 +29,13 @@ class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): stream: Whether to stream the completion or not. `CompletionChunkEvent`s will be published to the `Structure` if one is provided. """ - temperature: float = field(default=0.1, kw_only=True, metadata={"serializable": True}) - max_tokens: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) - structure: Optional[Structure] = field(default=None, kw_only=True) - ignored_exception_types: tuple[type[Exception], ...] = field( - default=Factory(lambda: (ImportError, ValueError)), kw_only=True - ) + temperature: float = field(default=0.1, metadata={"serializable": True}) + max_tokens: Optional[int] = field(default=None, metadata={"serializable": True}) + structure: Optional[Structure] = field(default=None) + ignored_exception_types: tuple[type[Exception], ...] = field(default=Factory(lambda: (ImportError, ValueError))) model: str = field(metadata={"serializable": True}) tokenizer: BaseTokenizer - stream: bool = field(default=False, kw_only=True, metadata={"serializable": True}) + stream: bool = field(default=False, metadata={"serializable": True}) def before_run(self, prompt_stack: PromptStack) -> None: if self.structure: diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index 3ff2c9e89..ca199011a 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -11,7 +11,7 @@ from cohere import Client -@define +@define(kw_only=True) class CoherePromptDriver(BasePromptDriver): """ Attributes: @@ -20,15 +20,13 @@ class CoherePromptDriver(BasePromptDriver): client: Custom `cohere.Client`. """ - api_key: str = field(kw_only=True, metadata={"serializable": False}) - model: str = field(kw_only=True, metadata={"serializable": True}) + api_key: str = field(metadata={"serializable": False}) + model: str = field(metadata={"serializable": True}) client: Client = field( - default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True), - kw_only=True, + default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True) ) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True), - kw_only=True, + default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True) ) def try_run(self, prompt_stack: PromptStack) -> TextArtifact: diff --git a/griptape/engines/query/__init__.py b/griptape/drivers/rerank/__init__.py similarity index 100% rename from griptape/engines/query/__init__.py rename to griptape/drivers/rerank/__init__.py diff --git a/griptape/drivers/rerank/base_rerank_driver.py b/griptape/drivers/rerank/base_rerank_driver.py new file mode 100644 index 000000000..975575d49 --- /dev/null +++ b/griptape/drivers/rerank/base_rerank_driver.py @@ -0,0 +1,9 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.artifacts import TextArtifact + + +@define(kw_only=True) +class BaseRerankDriver(ABC): + @abstractmethod + def run(self, query: str, artifacts: list[TextArtifact]) -> list[TextArtifact]: ... diff --git a/griptape/drivers/rerank/cohere_rerank_driver.py b/griptape/drivers/rerank/cohere_rerank_driver.py new file mode 100644 index 000000000..206706476 --- /dev/null +++ b/griptape/drivers/rerank/cohere_rerank_driver.py @@ -0,0 +1,31 @@ +from __future__ import annotations +from typing import TYPE_CHECKING, Optional +from attrs import define, field, Factory +from griptape.artifacts import TextArtifact +from griptape.drivers import BaseRerankDriver +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from cohere import Client + + +@define(kw_only=True) +class CohereRerankDriver(BaseRerankDriver): + model: str = field(default="rerank-english-v3.0", metadata={"serializable": True}) + top_n: Optional[int] = field(default=None) + + api_key: str = field(metadata={"serializable": True}) + client: Client = field( + default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True) + ) + + def run(self, query: str, artifacts: list[TextArtifact]) -> list[TextArtifact]: + response = self.client.rerank( + model=self.model, + query=query, + documents=[a.value for a in artifacts], + return_documents=True, + top_n=self.top_n, + ) + + return [TextArtifact(r.document.text) for r in response.results] diff --git a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py index 2e9968b63..e29a7fa70 100644 --- a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py +++ b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py @@ -16,7 +16,7 @@ def query( include_vectors: bool = False, offset: Optional[int] = None, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Queries the MongoDB collection for documents that match the provided query string. Results can be customized based on parameters like count, namespace, inclusion of vectors, offset, and index. @@ -50,7 +50,7 @@ def query( pipeline.append({"$project": {"similarityScore": {"$meta": "searchScore"}, "document": "$$ROOT"}}) return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=str(doc["_id"]), vector=doc[self.vector_path] if include_vectors else [], score=doc["similarityScore"], diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 55a758da1..71f1c1061 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -2,33 +2,34 @@ from abc import ABC, abstractmethod from concurrent import futures from dataclasses import dataclass -from attrs import define, field, Factory +from typing import Any from typing import Optional +from attrs import define, field, Factory from griptape import utils -from griptape.mixins import SerializableMixin -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact from griptape.drivers import BaseEmbeddingDriver +from griptape.mixins import SerializableMixin @define class BaseVectorStoreDriver(SerializableMixin, ABC): DEFAULT_QUERY_COUNT = 5 - @dataclass - class QueryResult: - id: str - vector: Optional[list[float]] - score: float - meta: Optional[dict] = None - namespace: Optional[str] = None - @dataclass class Entry: id: str - vector: list[float] + vector: Optional[list[float]] = None + score: Optional[float] = None meta: Optional[dict] = None namespace: Optional[str] = None + @staticmethod + def from_dict(data: dict[str, Any]) -> BaseVectorStoreDriver.Entry: + return BaseVectorStoreDriver.Entry(**data) + + def to_artifact(self) -> BaseArtifact: + return BaseArtifact.from_json(self.meta["artifact"]) # pyright: ignore[reportOptionalSubscript] + embedding_driver: BaseEmbeddingDriver = field(kw_only=True, metadata={"serializable": True}) futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) @@ -44,22 +45,30 @@ def upsert_text_artifacts( ) def upsert_text_artifact( - self, artifact: TextArtifact, namespace: Optional[str] = None, meta: Optional[dict] = None, **kwargs + self, + artifact: TextArtifact, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + vector_id: Optional[str] = None, + **kwargs, ) -> str: - if not meta: - meta = {} + meta = {} if meta is None else meta + vector_id = utils.str_to_hash(artifact.value) if vector_id is None else vector_id - meta["artifact"] = artifact.to_json() - - if artifact.embedding: - vector = artifact.embedding + if self.does_entry_exist(vector_id, namespace): + return vector_id else: - vector = artifact.generate_embedding(self.embedding_driver) + meta["artifact"] = artifact.to_json() - if isinstance(vector, list): - return self.upsert_vector(vector, vector_id=artifact.id, namespace=namespace, meta=meta, **kwargs) - else: - raise ValueError("Vector must be an instance of 'list'.") + if artifact.embedding: + vector = artifact.embedding + else: + vector = artifact.generate_embedding(self.embedding_driver) + + if isinstance(vector, list): + return self.upsert_vector(vector, vector_id=vector_id, namespace=namespace, meta=meta, **kwargs) + else: + raise ValueError("Vector must be an instance of 'list'.") def upsert_text( self, @@ -69,13 +78,27 @@ def upsert_text( meta: Optional[dict] = None, **kwargs, ) -> str: - return self.upsert_vector( - self.embedding_driver.embed_string(string), - vector_id=vector_id, - namespace=namespace, - meta=meta if meta else {}, - **kwargs, - ) + vector_id = utils.str_to_hash(string) if vector_id is None else vector_id + + if self.does_entry_exist(vector_id, namespace): + return vector_id + else: + return self.upsert_vector( + self.embedding_driver.embed_string(string), + vector_id=vector_id, + namespace=namespace, + meta=meta if meta else {}, + **kwargs, + ) + + def does_entry_exist(self, vector_id: str, namespace: Optional[str] = None) -> bool: + return self.load_entry(vector_id, namespace) is not None + + def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: + result = self.load_entries(namespace) + artifacts = [r.to_artifact() for r in result] + + return ListArtifact([a for a in artifacts if isinstance(a, TextArtifact)]) @abstractmethod def delete_vector(self, vector_id: str) -> None: ... @@ -104,4 +127,4 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[QueryResult]: ... + ) -> list[Entry]: ... diff --git a/griptape/drivers/vector/dummy_vector_store_driver.py b/griptape/drivers/vector/dummy_vector_store_driver.py index f53a5eb90..04dea2181 100644 --- a/griptape/drivers/vector/dummy_vector_store_driver.py +++ b/griptape/drivers/vector/dummy_vector_store_driver.py @@ -36,5 +36,5 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: raise DummyException(__class__.__name__, "query") diff --git a/griptape/drivers/vector/local_vector_store_driver.py b/griptape/drivers/vector/local_vector_store_driver.py index 4b9dae00f..1a86225c6 100644 --- a/griptape/drivers/vector/local_vector_store_driver.py +++ b/griptape/drivers/vector/local_vector_store_driver.py @@ -1,15 +1,49 @@ -from typing import Optional, Callable +import json +import os +import threading +from dataclasses import asdict +from typing import Optional, Callable, TextIO +from attrs import define, field, Factory from numpy import dot from numpy.linalg import norm from griptape import utils from griptape.drivers import BaseVectorStoreDriver -from attrs import define, field -@define +@define(kw_only=True) class LocalVectorStoreDriver(BaseVectorStoreDriver): - entries: dict[str, BaseVectorStoreDriver.Entry] = field(factory=dict, kw_only=True) - relatedness_fn: Callable = field(default=lambda x, y: dot(x, y) / (norm(x) * norm(y)), kw_only=True) + entries: dict[str, BaseVectorStoreDriver.Entry] = field(factory=dict) + persist_file: Optional[str] = field(default=None) + relatedness_fn: Callable = field(default=lambda x, y: dot(x, y) / (norm(x) * norm(y))) + thread_lock: threading.Lock = field(default=Factory(lambda: threading.Lock())) + + def __attrs_post_init__(self) -> None: + if self.persist_file is not None: + directory = os.path.dirname(self.persist_file) + + if directory and not os.path.exists(directory): + os.makedirs(directory) + + if not os.path.isfile(self.persist_file): + with open(self.persist_file, "w") as file: + self.save_entries_to_file(file) + + with open(self.persist_file, "r+") as file: + if os.path.getsize(self.persist_file) > 0: + self.entries = self.load_entries_from_file(file) + else: + self.save_entries_to_file(file) + + def save_entries_to_file(self, json_file: TextIO) -> None: + with self.thread_lock: + serialized_data = {k: asdict(v) for k, v in self.entries.items()} + + json.dump(serialized_data, json_file) + + def load_entries_from_file(self, json_file: TextIO) -> dict[str, BaseVectorStoreDriver.Entry]: + data = json.load(json_file) + + return {k: BaseVectorStoreDriver.Entry.from_dict(v) for k, v in data.items()} def upsert_vector( self, @@ -21,9 +55,16 @@ def upsert_vector( ) -> str: vector_id = vector_id if vector_id else utils.str_to_hash(str(vector)) - self.entries[self._namespaced_vector_id(vector_id, namespace)] = self.Entry( - id=vector_id, vector=vector, meta=meta, namespace=namespace - ) + with self.thread_lock: + self.entries[self._namespaced_vector_id(vector_id, namespace)] = self.Entry( + id=vector_id, vector=vector, meta=meta, namespace=namespace + ) + + if self.persist_file is not None: + # TODO: optimize later since it reserializes all entries from memory and stores them in the JSON file + # every time a new vector is inserted + with open(self.persist_file, "w") as file: + self.save_entries_to_file(file) return vector_id @@ -40,7 +81,7 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: query_embedding = self.embedding_driver.embed_string(query) if namespace: @@ -54,7 +95,7 @@ def query( entries_and_relatednesses.sort(key=lambda x: x[1], reverse=True) result = [ - BaseVectorStoreDriver.QueryResult(id=er[0].id, vector=er[0].vector, score=er[1], meta=er[0].meta) + BaseVectorStoreDriver.Entry(id=er[0].id, vector=er[0].vector, score=er[1], meta=er[0].meta) for er in entries_and_relatednesses ][:count] @@ -62,12 +103,12 @@ def query( return result else: return [ - BaseVectorStoreDriver.QueryResult(id=r.id, vector=[], score=r.score, meta=r.meta, namespace=r.namespace) + BaseVectorStoreDriver.Entry(id=r.id, vector=[], score=r.score, meta=r.meta, namespace=r.namespace) for r in result ] - def _namespaced_vector_id(self, vector_id: str, namespace: Optional[str]): - return vector_id if namespace is None else f"{namespace}-{vector_id}" - def delete_vector(self, vector_id: str): raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") + + def _namespaced_vector_id(self, vector_id: str, namespace: Optional[str]): + return vector_id if namespace is None else f"{namespace}-{vector_id}" diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index cccc716f8..f20530cff 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -1,5 +1,6 @@ from __future__ import annotations from typing import Optional, Any, TYPE_CHECKING +from griptape import utils from griptape.utils import import_optional_dependency from griptape.drivers import BaseVectorStoreDriver from griptape.artifacts import TextArtifact @@ -65,7 +66,12 @@ def upsert_text( raise ValueError(f"Failed to upsert text: {response}") def upsert_text_artifact( - self, artifact: TextArtifact, namespace: Optional[str] = None, meta: Optional[dict] = None, **kwargs + self, + artifact: TextArtifact, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + vector_id: Optional[str] = None, + **kwargs, ) -> str: """Upsert a text artifact into the Marqo index. @@ -73,15 +79,17 @@ def upsert_text_artifact( artifact: The text artifact to be indexed. namespace: An optional namespace for the artifact. meta: An optional dictionary of metadata for the artifact. + vector_id: An optional explicit vector_id. Returns: str: The ID of the artifact that was added. """ artifact_json = artifact.to_json() + vector_id = utils.str_to_hash(artifact.value) if vector_id is None else vector_id doc = { - "_id": artifact.id, + "_id": vector_id, "Description": artifact.value, # Description will be treated as tensor field "artifact": str(artifact_json), "namespace": namespace, @@ -160,7 +168,7 @@ def query( include_vectors: bool = False, include_metadata: bool = True, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Query the Marqo index for documents. Args: @@ -188,7 +196,7 @@ def query( ] return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=r["_id"], vector=r["_tensor_facets"][0]["_embedding"] if include_vectors else [], score=r["_score"], diff --git a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py index c5368de3d..73bcc02c7 100644 --- a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py +++ b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py @@ -110,7 +110,7 @@ def query( include_vectors: bool = False, offset: Optional[int] = None, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Queries the MongoDB collection for documents that match the provided query string. Results can be customized based on parameters like count, namespace, inclusion of vectors, offset, and index. @@ -148,7 +148,7 @@ def query( pipeline[0]["$vectorSearch"]["filter"] = {"namespace": namespace} results = [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=str(doc["_id"]), vector=doc[self.vector_path] if include_vectors else [], score=doc["score"], diff --git a/griptape/drivers/vector/opensearch_vector_store_driver.py b/griptape/drivers/vector/opensearch_vector_store_driver.py index 7ff00d2de..81add74aa 100644 --- a/griptape/drivers/vector/opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/opensearch_vector_store_driver.py @@ -127,13 +127,13 @@ def query( include_metadata=True, field_name: str = "vector", **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Performs a nearest neighbor search on OpenSearch to find vectors similar to the provided query string. Results can be limited using the count parameter and optionally filtered by a namespace. Returns: - A list of BaseVectorStoreDriver.QueryResult objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. + A list of BaseVectorStoreDriver.Entry objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. """ count = count if count else BaseVectorStoreDriver.DEFAULT_QUERY_COUNT vector = self.embedding_driver.embed_string(query) @@ -150,7 +150,7 @@ def query( response = self.client.search(index=self.index_name, body=query_body) return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=hit["_id"], namespace=hit["_source"].get("namespace") if namespace else None, score=hit["_score"], diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index 8058c8774..29c657589 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -127,7 +127,7 @@ def query( include_vectors: bool = False, distance_metric: str = "cosine_distance", **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Performs a search on the collection to find vectors similar to the provided input vector, optionally filtering to only those that match the provided namespace. """ @@ -163,7 +163,7 @@ def query( results = query_result.limit(count).all() return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=str(result[0].id), vector=result[0].vector if include_vectors else None, score=result[1], diff --git a/griptape/drivers/vector/pinecone_vector_store_driver.py b/griptape/drivers/vector/pinecone_vector_store_driver.py index daf378087..6da2f2418 100644 --- a/griptape/drivers/vector/pinecone_vector_store_driver.py +++ b/griptape/drivers/vector/pinecone_vector_store_driver.py @@ -77,7 +77,7 @@ def query( # PineconeVectorStorageDriver-specific params: include_metadata=True, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: vector = self.embedding_driver.embed_string(query) params = { @@ -90,7 +90,7 @@ def query( results = self.index.query(vector=vector, **params) return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=r["id"], vector=r["values"], score=r["score"], meta=r["metadata"], namespace=results["namespace"] ) for r in results["matches"] diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index 6e39775b7..e58e4b3ea 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -1,14 +1,11 @@ from __future__ import annotations import json -import logging import numpy as np from griptape.utils import import_optional_dependency, str_to_hash from typing import Optional, TYPE_CHECKING from attrs import define, field, Factory from griptape.drivers import BaseVectorStoreDriver -logging.basicConfig(level=logging.WARNING) - if TYPE_CHECKING: from redis import Redis @@ -111,13 +108,13 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Performs a nearest neighbor search on Redis to find vectors similar to the provided input vector. Results can be limited using the count parameter and optionally filtered by a namespace. Returns: - A list of BaseVectorStoreDriver.QueryResult objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. + A list of BaseVectorStoreDriver.Entry objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. """ Query = import_optional_dependency("redis.commands.search.query").Query @@ -143,7 +140,7 @@ def query( vector_id = document.id.split(":")[1] if ":" in document.id else document.id vector_float_list = json.loads(document.vec_string) if include_vectors else None query_results.append( - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=vector_id, vector=vector_float_list, score=float(document.score), diff --git a/griptape/engines/__init__.py b/griptape/engines/__init__.py index 17adaa53d..7835b2238 100644 --- a/griptape/engines/__init__.py +++ b/griptape/engines/__init__.py @@ -1,8 +1,6 @@ from .extraction.base_extraction_engine import BaseExtractionEngine from .extraction.csv_extraction_engine import CsvExtractionEngine from .extraction.json_extraction_engine import JsonExtractionEngine -from .query.base_query_engine import BaseQueryEngine -from .query.vector_query_engine import VectorQueryEngine from .summary.base_summary_engine import BaseSummaryEngine from .summary.prompt_summary_engine import PromptSummaryEngine from .image.base_image_generation_engine import BaseImageGenerationEngine @@ -15,8 +13,6 @@ from .audio.audio_transcription_engine import AudioTranscriptionEngine __all__ = [ - "BaseQueryEngine", - "VectorQueryEngine", "BaseSummaryEngine", "PromptSummaryEngine", "BaseExtractionEngine", diff --git a/griptape/engines/query/base_query_engine.py b/griptape/engines/query/base_query_engine.py deleted file mode 100644 index 61a488547..000000000 --- a/griptape/engines/query/base_query_engine.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import annotations -from abc import ABC, abstractmethod -from attrs import define -from typing import Optional -from griptape.artifacts import TextArtifact, ListArtifact -from griptape.rules import Ruleset - - -@define -class BaseQueryEngine(ABC): - @abstractmethod - def query( - self, - query: str, - namespace: Optional[str] = None, - *, - rulesets: Optional[list[Ruleset]] = None, - top_n: Optional[int] = None, - filter: Optional[dict] = None, - ) -> TextArtifact: ... - - @abstractmethod - def load_artifacts(self, namespace: str) -> ListArtifact: ... - - @abstractmethod - def upsert_text_artifact(self, artifact: TextArtifact, namespace: Optional[str] = None) -> str: ... - - @abstractmethod - def upsert_text_artifacts(self, artifacts: list[TextArtifact], namespace: str) -> None: ... diff --git a/griptape/engines/query/vector_query_engine.py b/griptape/engines/query/vector_query_engine.py deleted file mode 100644 index 24338b348..000000000 --- a/griptape/engines/query/vector_query_engine.py +++ /dev/null @@ -1,95 +0,0 @@ -from __future__ import annotations -from typing import TYPE_CHECKING, Optional -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact -from griptape.utils import PromptStack -from griptape.engines import BaseQueryEngine -from griptape.utils.j2 import J2 -from griptape.rules import Ruleset - -if TYPE_CHECKING: - from griptape.drivers import BaseVectorStoreDriver, BasePromptDriver - - -@define -class VectorQueryEngine(BaseQueryEngine): - answer_token_offset: int = field(default=400, kw_only=True) - vector_store_driver: BaseVectorStoreDriver = field(kw_only=True) - prompt_driver: BasePromptDriver = field(kw_only=True) - user_template_generator: J2 = field(default=Factory(lambda: J2("engines/query/user.j2")), kw_only=True) - system_template_generator: J2 = field(default=Factory(lambda: J2("engines/query/system.j2")), kw_only=True) - - def query( - self, - query: str, - namespace: Optional[str] = None, - *, - rulesets: Optional[list[Ruleset]] = None, - metadata: Optional[str] = None, - top_n: Optional[int] = None, - filter: Optional[dict] = None, - ) -> TextArtifact: - tokenizer = self.prompt_driver.tokenizer - result = self.vector_store_driver.query(query, top_n, namespace, filter=filter) - artifacts = [ - artifact - for artifact in [BaseArtifact.from_json(r.meta["artifact"]) for r in result if r.meta] - if isinstance(artifact, TextArtifact) - ] - text_segments = [] - user_message = "" - system_message = "" - - for artifact in artifacts: - text_segments.append(artifact.value) - system_message = self.system_template_generator.render( - rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets), - metadata=metadata, - text_segments=text_segments, - ) - user_message = self.user_template_generator.render(query=query) - - message_token_count = self.prompt_driver.tokenizer.count_input_tokens_left( - self.prompt_driver.prompt_stack_to_string( - PromptStack( - inputs=[ - PromptStack.Input(system_message, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(user_message, role=PromptStack.USER_ROLE), - ] - ) - ) - ) - - if message_token_count + self.answer_token_offset >= tokenizer.max_input_tokens: - text_segments.pop() - - system_message = self.system_template_generator.render( - rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets), - metadata=metadata, - text_segments=text_segments, - ) - - break - - return self.prompt_driver.run( - PromptStack( - inputs=[ - PromptStack.Input(system_message, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(user_message, role=PromptStack.USER_ROLE), - ] - ) - ) - - def upsert_text_artifact(self, artifact: TextArtifact, namespace: Optional[str] = None) -> str: - result = self.vector_store_driver.upsert_text_artifact(artifact, namespace=namespace) - - return result - - def upsert_text_artifacts(self, artifacts: list[TextArtifact], namespace: str) -> None: - self.vector_store_driver.upsert_text_artifacts({namespace: artifacts}) - - def load_artifacts(self, namespace: str) -> ListArtifact: - result = self.vector_store_driver.load_entries(namespace) - artifacts = [BaseArtifact.from_json(r.meta["artifact"]) for r in result if r.meta and r.meta.get("artifact")] - - return ListArtifact([a for a in artifacts if isinstance(a, TextArtifact)]) diff --git a/griptape/engines/rag/__init__.py b/griptape/engines/rag/__init__.py new file mode 100644 index 000000000..f009772fb --- /dev/null +++ b/griptape/engines/rag/__init__.py @@ -0,0 +1,4 @@ +from .rag_context import RagContext +from .rag_engine import RagEngine + +__all__ = ["RagContext", "RagEngine"] diff --git a/griptape/engines/rag/modules/__init__.py b/griptape/engines/rag/modules/__init__.py new file mode 100644 index 000000000..a9550d8bb --- /dev/null +++ b/griptape/engines/rag/modules/__init__.py @@ -0,0 +1,29 @@ +from .base_rag_module import BaseRagModule +from .query.base_query_rag_module import BaseQueryRagModule +from .query.related_query_generation_rag_module import RelatedQueryGenerationRagModule +from .retrieval.base_retrieval_rag_module import BaseRetrievalRagModule +from .retrieval.base_rerank_rag_module import BaseRerankRagModule +from .retrieval.text_rerank_rag_module import TextRerankRagModule +from .retrieval.text_retrieval_rag_module import TextRetrievalRagModule +from .generation.base_before_generation_rag_module import BaseBeforeGenerationRagModule +from .generation.base_after_generation_rag_module import BaseAfterGenerationRagModule +from .generation.base_generation_rag_module import BaseGenerationRagModule +from .generation.prompt_generation_rag_module import PromptGenerationRagModule +from .generation.rulesets_generation_rag_module import RulesetsGenerationRagModule +from .generation.metadata_generation_rag_module import MetadataGenerationRagModule + +__all__ = [ + "BaseRagModule", + "BaseQueryRagModule", + "RelatedQueryGenerationRagModule", + "BaseRetrievalRagModule", + "BaseRerankRagModule", + "TextRerankRagModule", + "TextRetrievalRagModule", + "BaseBeforeGenerationRagModule", + "BaseAfterGenerationRagModule", + "BaseGenerationRagModule", + "PromptGenerationRagModule", + "RulesetsGenerationRagModule", + "MetadataGenerationRagModule", +] diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py new file mode 100644 index 000000000..958cbd46c --- /dev/null +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -0,0 +1,18 @@ +from abc import ABC +from concurrent import futures +from attrs import define, field, Factory + +from griptape.utils import PromptStack + + +@define(kw_only=True) +class BaseRagModule(ABC): + futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor())) + + def generate_query_prompt_stack(self, system_prompt: str, query: str) -> PromptStack: + return PromptStack( + inputs=[ + PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), + PromptStack.Input(query, role=PromptStack.USER_ROLE), + ] + ) diff --git a/tests/unit/engines/query/__init__.py b/griptape/engines/rag/modules/generation/__init__.py similarity index 100% rename from tests/unit/engines/query/__init__.py rename to griptape/engines/rag/modules/generation/__init__.py diff --git a/griptape/engines/rag/modules/generation/base_after_generation_rag_module.py b/griptape/engines/rag/modules/generation/base_after_generation_rag_module.py new file mode 100644 index 000000000..f3a26e9db --- /dev/null +++ b/griptape/engines/rag/modules/generation/base_after_generation_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseAfterGenerationRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/generation/base_before_generation_rag_module.py b/griptape/engines/rag/modules/generation/base_before_generation_rag_module.py new file mode 100644 index 000000000..6a57bd6af --- /dev/null +++ b/griptape/engines/rag/modules/generation/base_before_generation_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseBeforeGenerationRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/generation/base_generation_rag_module.py b/griptape/engines/rag/modules/generation/base_generation_rag_module.py new file mode 100644 index 000000000..08f1b5323 --- /dev/null +++ b/griptape/engines/rag/modules/generation/base_generation_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseGenerationRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/generation/metadata_generation_rag_module.py b/griptape/engines/rag/modules/generation/metadata_generation_rag_module.py new file mode 100644 index 000000000..1ce689960 --- /dev/null +++ b/griptape/engines/rag/modules/generation/metadata_generation_rag_module.py @@ -0,0 +1,20 @@ +from typing import Optional +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseBeforeGenerationRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class MetadataGenerationRagModule(BaseBeforeGenerationRagModule): + metadata: Optional[str] = field(default=None) + + def run(self, context: RagContext) -> RagContext: + metadata = context.metadata if self.metadata is None else self.metadata + + if metadata is not None: + context.before_query.append( + J2("engines/rag/modules/metadata_generation/system.j2").render(metadata=metadata) + ) + + return context diff --git a/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py b/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py new file mode 100644 index 000000000..9e7c3b08f --- /dev/null +++ b/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py @@ -0,0 +1,54 @@ +from typing import Callable +from attrs import define, field, Factory +from griptape.drivers import BasePromptDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseGenerationRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class PromptGenerationRagModule(BaseGenerationRagModule): + answer_token_offset: int = field(default=400) + prompt_driver: BasePromptDriver = field() + generate_system_template: Callable[[list[str], list[str], list[str]], str] = field( + default=Factory(lambda self: self.default_system_template_generator, takes_self=True) + ) + + def run(self, context: RagContext) -> RagContext: + query = context.initial_query + before_query = context.before_query + after_query = context.after_query + text_artifact_chunks = context.text_chunks + + if query: + tokenizer = self.prompt_driver.tokenizer + text_chunks = [] + system_prompt = "" + + for artifact in text_artifact_chunks: + text_chunks.append(artifact.value) + + system_prompt = self.generate_system_template(text_chunks, before_query, after_query) + message_token_count = self.prompt_driver.tokenizer.count_tokens( + self.prompt_driver.prompt_stack_to_string(self.generate_query_prompt_stack(system_prompt, query)) + ) + + if message_token_count + self.answer_token_offset >= tokenizer.max_input_tokens: + text_chunks.pop() + + system_prompt = self.generate_system_template(text_chunks, before_query, after_query) + + break + + context.output = self.prompt_driver.run(self.generate_query_prompt_stack(system_prompt, query)) + + return context + + def default_system_template_generator( + self, text_chunks: list[str], before_system_prompt: list, after_system_prompt: list + ) -> str: + return J2("engines/rag/modules/prompt_generation/system.j2").render( + text_chunks=text_chunks, + before_system_prompt="\n\n".join(before_system_prompt), + after_system_prompt="\n\n".join(after_system_prompt), + ) diff --git a/griptape/engines/rag/modules/generation/rulesets_generation_rag_module.py b/griptape/engines/rag/modules/generation/rulesets_generation_rag_module.py new file mode 100644 index 000000000..ff29c379a --- /dev/null +++ b/griptape/engines/rag/modules/generation/rulesets_generation_rag_module.py @@ -0,0 +1,15 @@ +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseBeforeGenerationRagModule +from griptape.rules import Ruleset +from griptape.utils import J2 + + +@define +class RulesetsGenerationRagModule(BaseBeforeGenerationRagModule): + rulesets: list[Ruleset] = field(kw_only=True) + + def run(self, context: RagContext) -> RagContext: + context.before_query.append(J2("rulesets/rulesets.j2").render(rulesets=self.rulesets)) + + return context diff --git a/griptape/engines/rag/modules/query/__init__.py b/griptape/engines/rag/modules/query/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/engines/rag/modules/query/base_query_rag_module.py b/griptape/engines/rag/modules/query/base_query_rag_module.py new file mode 100644 index 000000000..c9eace864 --- /dev/null +++ b/griptape/engines/rag/modules/query/base_query_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseQueryRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> list[str]: ... diff --git a/griptape/engines/rag/modules/query/related_query_generation_rag_module.py b/griptape/engines/rag/modules/query/related_query_generation_rag_module.py new file mode 100644 index 000000000..4661e24a2 --- /dev/null +++ b/griptape/engines/rag/modules/query/related_query_generation_rag_module.py @@ -0,0 +1,33 @@ +from typing import Callable +from attrs import define, field, Factory +from griptape import utils +from griptape.drivers import BasePromptDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseQueryRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class RelatedQueryGenerationRagModule(BaseQueryRagModule): + query_count: int = field(default=5) + prompt_driver: BasePromptDriver = field() + generate_system_template: Callable[[str], str] = field( + default=Factory(lambda self: self.default_system_template_generator, takes_self=True), kw_only=True + ) + + def run(self, context: RagContext) -> list[str]: + system_prompt = self.generate_system_template(context.initial_query) + + results = utils.execute_futures_list( + [ + self.futures_executor.submit( + self.prompt_driver.run, self.generate_query_prompt_stack(system_prompt, "Alternative query: ") + ) + for _ in range(self.query_count) + ] + ) + + return [r.value for r in results] + + def default_system_template_generator(self, initial_query: str) -> str: + return J2("engines/rag/modules/query_generation/system.j2").render(initial_query=initial_query) diff --git a/griptape/engines/rag/modules/retrieval/__init__.py b/griptape/engines/rag/modules/retrieval/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py b/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py new file mode 100644 index 000000000..8ecf9f046 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py @@ -0,0 +1,16 @@ +from abc import ABC, abstractmethod +from typing import Sequence + +from attrs import define, field +from griptape.artifacts import BaseArtifact +from griptape.drivers import BaseRerankDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseRerankRagModule(BaseRagModule, ABC): + rerank_driver: BaseRerankDriver = field() + + @abstractmethod + def run(self, context: RagContext) -> Sequence[BaseArtifact]: ... diff --git a/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py new file mode 100644 index 000000000..f11537d9f --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +from typing import Sequence +from attrs import define +from griptape.artifacts import BaseArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseRetrievalRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> Sequence[BaseArtifact]: ... diff --git a/griptape/engines/rag/modules/retrieval/text_rerank_rag_module.py b/griptape/engines/rag/modules/retrieval/text_rerank_rag_module.py new file mode 100644 index 000000000..a766d0cb6 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/text_rerank_rag_module.py @@ -0,0 +1,12 @@ +from typing import Sequence + +from attrs import define +from griptape.artifacts import BaseArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRerankRagModule + + +@define(kw_only=True) +class TextRerankRagModule(BaseRerankRagModule): + def run(self, context: RagContext) -> Sequence[BaseArtifact]: + return self.rerank_driver.run(context.initial_query, context.text_chunks) diff --git a/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py new file mode 100644 index 000000000..5c6bedac4 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py @@ -0,0 +1,35 @@ +from __future__ import annotations +import itertools +from typing import TYPE_CHECKING, Optional, Sequence +from attrs import define, field +from griptape import utils +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRetrievalRagModule + +if TYPE_CHECKING: + from griptape.drivers import BaseVectorStoreDriver + + +@define(kw_only=True) +class TextRetrievalRagModule(BaseRetrievalRagModule): + vector_store_driver: BaseVectorStoreDriver = field() + namespace: Optional[str] = field(default=None) + top_n: Optional[int] = field(default=None) + + def run(self, context: RagContext) -> Sequence[TextArtifact]: + all_queries = [context.initial_query] + context.alternative_queries + namespace = self.namespace or context.namespace + + results = utils.execute_futures_list( + [ + self.futures_executor.submit(self.vector_store_driver.query, query, self.top_n, namespace, False) + for query in all_queries + ] + ) + + return [ + artifact + for artifact in [r.to_artifact() for r in list(itertools.chain.from_iterable(results))] + if isinstance(artifact, TextArtifact) + ] diff --git a/griptape/engines/rag/rag_context.py b/griptape/engines/rag/rag_context.py new file mode 100644 index 000000000..5f8ce9d6a --- /dev/null +++ b/griptape/engines/rag/rag_context.py @@ -0,0 +1,29 @@ +from typing import Optional +from attrs import define, field +from griptape.artifacts import TextArtifact + + +@define(kw_only=True) +class RagContext: + """Used by RagEngine stages and module to pass context that individual modules are expected to update in the `run` + method. + + Attributes: + initial_query: Query provided by the user. + namespace: Optional namespace override for modules with an explicit namespace parameter. + metadata: Optional metadata override for modules with an explicit metadata parameter. + alternative_queries: Optional queries to expand retrieval results. + before_query: An optional list of strings to add before the query in generation modules. + after_query: An optional list of strings to add after the query in generation modules. + text_chunks: A list of text chunks to pass around from the retrieval stage to the generation stage. + output: Final output from the generation stage. + """ + + initial_query: str = field() + namespace: Optional[str] = field(default=None) + metadata: Optional[str] = field(default=None) + alternative_queries: list[str] = field(factory=list) + before_query: list[str] = field(factory=list) + after_query: list[str] = field(factory=list) + text_chunks: list[TextArtifact] = field(factory=list) + output: Optional[TextArtifact] = field(default=None) diff --git a/griptape/engines/rag/rag_engine.py b/griptape/engines/rag/rag_engine.py new file mode 100644 index 000000000..1c2176128 --- /dev/null +++ b/griptape/engines/rag/rag_engine.py @@ -0,0 +1,26 @@ +from typing import Optional +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.stages import QueryRagStage, GenerationRagStage, RetrievalRagStage + + +@define(kw_only=True) +class RagEngine: + query_stage: Optional[QueryRagStage] = field(default=None) + retrieval_stage: Optional[RetrievalRagStage] = field(default=None) + generation_stage: Optional[GenerationRagStage] = field(default=None) + + def process_query(self, query: str) -> RagContext: + return self.process(RagContext(initial_query=query)) + + def process(self, context: RagContext) -> RagContext: + if self.query_stage: + context = self.query_stage.run(context) + + if self.retrieval_stage: + context = self.retrieval_stage.run(context) + + if self.generation_stage: + context = self.generation_stage.run(context) + + return context diff --git a/griptape/engines/rag/stages/__init__.py b/griptape/engines/rag/stages/__init__.py new file mode 100644 index 000000000..85a603d03 --- /dev/null +++ b/griptape/engines/rag/stages/__init__.py @@ -0,0 +1,6 @@ +from .base_rag_stage import BaseRagStage +from .retrieval_rag_stage import RetrievalRagStage +from .query_rag_stage import QueryRagStage +from .generation_rag_stage import GenerationRagStage + +__all__ = ["BaseRagStage", "RetrievalRagStage", "QueryRagStage", "GenerationRagStage"] diff --git a/griptape/engines/rag/stages/base_rag_stage.py b/griptape/engines/rag/stages/base_rag_stage.py new file mode 100644 index 000000000..786975b82 --- /dev/null +++ b/griptape/engines/rag/stages/base_rag_stage.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +from concurrent import futures +from attrs import define, field, Factory +from griptape.engines.rag import RagContext + + +@define(kw_only=True) +class BaseRagStage(ABC): + futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor())) + + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/stages/generation_rag_stage.py b/griptape/engines/rag/stages/generation_rag_stage.py new file mode 100644 index 000000000..60102889a --- /dev/null +++ b/griptape/engines/rag/stages/generation_rag_stage.py @@ -0,0 +1,33 @@ +import logging +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import ( + BaseGenerationRagModule, + BaseBeforeGenerationRagModule, + BaseAfterGenerationRagModule, +) +from griptape.engines.rag.stages import BaseRagStage + + +@define(kw_only=True) +class GenerationRagStage(BaseRagStage): + before_generator_modules: list[BaseBeforeGenerationRagModule] = field(factory=list) + generation_module: BaseGenerationRagModule = field() + after_generator_modules: list[BaseAfterGenerationRagModule] = field(factory=list) + + def run(self, context: RagContext) -> RagContext: + logging.info(f"GenerationStage: running {len(self.before_generator_modules)} before modules sequentially") + + for generator in self.before_generator_modules: + context = generator.run(context) + + logging.info("GenerationStage: running generation module") + + context = self.generation_module.run(context) + + logging.info(f"GenerationStage: running {len(self.after_generator_modules)} after modules sequentially") + + for generator in self.after_generator_modules: + context = generator.run(context) + + return context diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py new file mode 100644 index 000000000..b122fa7a6 --- /dev/null +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -0,0 +1,23 @@ +import itertools +import logging +from attrs import define, field +from griptape import utils +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseQueryRagModule +from griptape.engines.rag.stages import BaseRagStage + + +@define(kw_only=True) +class QueryRagStage(BaseRagStage): + query_generation_modules: list[BaseQueryRagModule] = field() + + def run(self, context: RagContext) -> RagContext: + logging.info(f"QueryStage: running {len(self.query_generation_modules)} query generation modules in parallel") + + results = utils.execute_futures_list( + [self.futures_executor.submit(r.run, context) for r in self.query_generation_modules] + ) + + context.alternative_queries = list(itertools.chain.from_iterable(results)) + + return context diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py new file mode 100644 index 000000000..8a0ceca44 --- /dev/null +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -0,0 +1,49 @@ +import itertools +import logging +from typing import Optional +from attrs import define, field +from griptape import utils +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRerankRagModule +from griptape.engines.rag.modules import BaseRetrievalRagModule +from griptape.engines.rag.stages import BaseRagStage + + +@define(kw_only=True) +class RetrievalRagStage(BaseRagStage): + retrieval_modules: list[BaseRetrievalRagModule] = field() + rerank_module: Optional[BaseRerankRagModule] = field(default=None) + max_chunks: Optional[int] = field(default=None) + + def run(self, context: RagContext) -> RagContext: + logging.info(f"RetrievalStage: running {len(self.retrieval_modules)} retrieval modules in parallel") + + results = utils.execute_futures_list( + [self.futures_executor.submit(r.run, context) for r in self.retrieval_modules] + ) + + # flatten the list of lists + results = list(itertools.chain.from_iterable(results)) + + # deduplicate the list + chunks_before_dedup = len(results) + results = list({str(c.value): c for c in results}.values()) + chunks_after_dedup = len(results) + + logging.info( + f"RetrievalStage: deduplicated {chunks_before_dedup - chunks_after_dedup} " + f"chunks ({chunks_before_dedup} - {chunks_after_dedup})" + ) + + context.text_chunks = [a for a in results if isinstance(a, TextArtifact)] + + if self.rerank_module: + logging.info(f"RetrievalStage: running rerank module on {chunks_after_dedup} chunks") + + context.text_chunks = [a for a in self.rerank_module.run(context) if isinstance(a, TextArtifact)] + + if self.max_chunks: + context.text_chunks = context.text_chunks[: self.max_chunks] + + return context diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 3b3162751..34d65a0c5 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -1,36 +1,50 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, Optional from attrs import define, field -from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact +from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact, InfoArtifact +from griptape.drivers import BaseVectorStoreDriver +from griptape.engines.rag import RagEngine, RagContext from griptape.memory.task.storage import BaseArtifactStorage if TYPE_CHECKING: - from griptape.engines import BaseSummaryEngine, CsvExtractionEngine, JsonExtractionEngine, VectorQueryEngine + from griptape.engines import BaseSummaryEngine, CsvExtractionEngine, JsonExtractionEngine -@define +@define(kw_only=True) class TextArtifactStorage(BaseArtifactStorage): - query_engine: VectorQueryEngine = field(kw_only=True) - summary_engine: Optional[BaseSummaryEngine] = field(kw_only=True, default=None) - csv_extraction_engine: Optional[CsvExtractionEngine] = field(kw_only=True, default=None) - json_extraction_engine: Optional[JsonExtractionEngine] = field(kw_only=True, default=None) + vector_store_driver: BaseVectorStoreDriver = field() + rag_engine: Optional[RagEngine] = field(default=None) + summary_engine: Optional[BaseSummaryEngine] = field(default=None) + csv_extraction_engine: Optional[CsvExtractionEngine] = field(default=None) + json_extraction_engine: Optional[JsonExtractionEngine] = field(default=None) def can_store(self, artifact: BaseArtifact) -> bool: return isinstance(artifact, TextArtifact) def store_artifact(self, namespace: str, artifact: BaseArtifact) -> None: if isinstance(artifact, TextArtifact): - self.query_engine.upsert_text_artifact(artifact, namespace) + self.vector_store_driver.upsert_text_artifact(artifact, namespace) else: raise ValueError("Artifact must be of instance TextArtifact") def load_artifacts(self, namespace: str) -> ListArtifact: - return self.query_engine.load_artifacts(namespace) + return self.vector_store_driver.load_artifacts(namespace) def summarize(self, namespace: str) -> TextArtifact: if self.summary_engine is None: raise ValueError("Summary engine is not set.") + return self.summary_engine.summarize_artifacts(self.load_artifacts(namespace)) - def query(self, namespace: str, query: str, metadata: Any = None) -> TextArtifact: - return self.query_engine.query(namespace=namespace, query=query, metadata=str(metadata) if metadata else None) + def query(self, namespace: str, query: str, metadata: Any = None) -> TextArtifact | InfoArtifact: + if self.rag_engine is None: + raise ValueError("RAG engine is not set.") + + result = self.rag_engine.process( + RagContext(initial_query=query, namespace=namespace, metadata=None if metadata is None else str(metadata)) + ).output + + if result is None: + return InfoArtifact("Empty output") + else: + return result diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 78dd69633..036e47cc8 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -1,19 +1,24 @@ from __future__ import annotations - import logging import uuid from abc import ABC, abstractmethod from logging import Logger from typing import TYPE_CHECKING, Any, Optional - from attrs import Factory, define, field from rich.logging import RichHandler - from griptape.artifacts import BlobArtifact, TextArtifact, BaseArtifact from griptape.config import BaseStructureConfig, OpenAiStructureConfig, StructureConfig from griptape.drivers import BaseEmbeddingDriver, BasePromptDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.drivers.vector.local_vector_store_driver import LocalVectorStoreDriver -from griptape.engines import CsvExtractionEngine, JsonExtractionEngine, PromptSummaryEngine, VectorQueryEngine +from griptape.engines import CsvExtractionEngine, JsonExtractionEngine, PromptSummaryEngine +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import ( + TextRetrievalRagModule, + RulesetsGenerationRagModule, + PromptGenerationRagModule, + MetadataGenerationRagModule, +) +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage from griptape.events import BaseEvent, EventListener from griptape.events.finish_structure_run_event import FinishStructureRunEvent from griptape.events.start_structure_run_event import StartStructureRunEvent @@ -52,7 +57,8 @@ class Structure(ABC): ), kw_only=True, ) - task_memory: Optional[TaskMemory] = field( + rag_engine: RagEngine = field(default=Factory(lambda self: self.default_rag_engine, takes_self=True), kw_only=True) + task_memory: TaskMemory = field( default=Factory(lambda self: self.default_task_memory, takes_self=True), kw_only=True ) meta_memory: MetaMemory = field(default=Factory(lambda: MetaMemory()), kw_only=True) @@ -163,14 +169,28 @@ def default_config(self) -> BaseStructureConfig: return config + @property + def default_rag_engine(self) -> RagEngine: + return RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[TextRetrievalRagModule(vector_store_driver=self.config.vector_store_driver)] + ), + generation_stage=GenerationRagStage( + before_generator_modules=[ + RulesetsGenerationRagModule(rulesets=self.rulesets), + MetadataGenerationRagModule(), + ], + generation_module=PromptGenerationRagModule(prompt_driver=self.config.prompt_driver), + ), + ) + @property def default_task_memory(self) -> TaskMemory: return TaskMemory( artifact_storages={ TextArtifact: TextArtifactStorage( - query_engine=VectorQueryEngine( - prompt_driver=self.config.prompt_driver, vector_store_driver=self.config.vector_store_driver - ), + rag_engine=self.rag_engine, + vector_store_driver=self.config.vector_store_driver, summary_engine=PromptSummaryEngine(prompt_driver=self.config.prompt_driver), csv_extraction_engine=CsvExtractionEngine(prompt_driver=self.config.prompt_driver), json_extraction_engine=JsonExtractionEngine(prompt_driver=self.config.prompt_driver), diff --git a/griptape/tasks/__init__.py b/griptape/tasks/__init__.py index 2c282adff..764d1669a 100644 --- a/griptape/tasks/__init__.py +++ b/griptape/tasks/__init__.py @@ -6,7 +6,7 @@ from .toolkit_task import ToolkitTask from .text_summary_task import TextSummaryTask from .tool_task import ToolTask -from .text_query_task import TextQueryTask +from .rag_task import RagTask from .extraction_task import ExtractionTask from .csv_extraction_task import CsvExtractionTask from .json_extraction_task import JsonExtractionTask @@ -31,7 +31,7 @@ "ToolkitTask", "TextSummaryTask", "ToolTask", - "TextQueryTask", + "RagTask", "ExtractionTask", "CsvExtractionTask", "JsonExtractionTask", diff --git a/griptape/tasks/rag_task.py b/griptape/tasks/rag_task.py new file mode 100644 index 000000000..d50e881c1 --- /dev/null +++ b/griptape/tasks/rag_task.py @@ -0,0 +1,31 @@ +from __future__ import annotations +from attrs import define, field +from griptape.artifacts import TextArtifact, ErrorArtifact +from griptape.engines.rag import RagEngine +from griptape.tasks import BaseTextInputTask + + +@define +class RagTask(BaseTextInputTask): + _rag_engine: RagEngine = field(kw_only=True, default=None, alias="rag_engine") + + @property + def rag_engine(self) -> RagEngine: + if self._rag_engine is None: + if self.structure is not None: + self._rag_engine = self.structure.rag_engine + else: + raise ValueError("rag_engine is not set.") + return self._rag_engine + + @rag_engine.setter + def rag_engine(self, value: RagEngine) -> None: + self._rag_engine = value + + def run(self) -> TextArtifact | ErrorArtifact: + result = self.rag_engine.process_query(self.input.to_text()).output + + if result is None: + return ErrorArtifact("empty output") + else: + return result diff --git a/griptape/tasks/text_query_task.py b/griptape/tasks/text_query_task.py deleted file mode 100644 index f35161c17..000000000 --- a/griptape/tasks/text_query_task.py +++ /dev/null @@ -1,35 +0,0 @@ -from attrs import define, field, Factory -from typing import Optional -from griptape.artifacts import TextArtifact -from griptape.engines import BaseQueryEngine, VectorQueryEngine -from griptape.loaders import TextLoader -from griptape.tasks import BaseTextInputTask - - -@define -class TextQueryTask(BaseTextInputTask): - _query_engine: BaseQueryEngine = field(kw_only=True, default=None, alias="query_engine") - loader: TextLoader = field(default=Factory(lambda: TextLoader()), kw_only=True) - namespace: Optional[str] = field(default=None, kw_only=True) - top_n: Optional[int] = field(default=None, kw_only=True) - - @property - def query_engine(self) -> BaseQueryEngine: - if self._query_engine is None: - if self.structure is not None: - self._query_engine = VectorQueryEngine( - prompt_driver=self.structure.config.prompt_driver, - vector_store_driver=self.structure.config.vector_store_driver, - ) - else: - raise ValueError("Query Engine is not set.") - return self._query_engine - - @query_engine.setter - def query_engine(self, value: BaseQueryEngine) -> None: - self._query_engine = value - - def run(self) -> TextArtifact: - return self.query_engine.query( - self.input.to_text(), namespace=self.namespace, rulesets=self.all_rulesets, top_n=self.top_n - ) diff --git a/griptape/templates/engines/rag/modules/metadata_generation/system.j2 b/griptape/templates/engines/rag/modules/metadata_generation/system.j2 new file mode 100644 index 000000000..601fc7a13 --- /dev/null +++ b/griptape/templates/engines/rag/modules/metadata_generation/system.j2 @@ -0,0 +1,5 @@ +{% if metadata %} +Metadata: """ +{{ metadata }} +""" +{% endif %} \ No newline at end of file diff --git a/griptape/templates/engines/rag/modules/prompt_generation/system.j2 b/griptape/templates/engines/rag/modules/prompt_generation/system.j2 new file mode 100644 index 000000000..85c1b9fa8 --- /dev/null +++ b/griptape/templates/engines/rag/modules/prompt_generation/system.j2 @@ -0,0 +1,15 @@ +{% if before_system_prompt %} +{{ before_system_prompt }} + +{% endif %} +You can answer questions by searching through text chunks. Always be truthful. Don't make up facts. Use the below list of text chunks to respond. If the answer cannot be found in the chunks, say "I could not find an answer." + +{% for chunk in text_chunks %} +Text chunk: """ +{{ chunk }} +""" +{% endfor %} +{% if after_system_prompt %} + +{{ after_system_prompt }} +{% endif %} \ No newline at end of file diff --git a/griptape/templates/engines/rag/modules/query_generation/system.j2 b/griptape/templates/engines/rag/modules/query_generation/system.j2 new file mode 100644 index 000000000..dd2a8e4bd --- /dev/null +++ b/griptape/templates/engines/rag/modules/query_generation/system.j2 @@ -0,0 +1,3 @@ +Given the following query, generate an alternative query that has the same meaning but uses different words and introduces other related terms. Don't say anything else. Only output an alternative query and nothing else. + +Query: {{ initial_query }} \ No newline at end of file diff --git a/griptape/tools/__init__.py b/griptape/tools/__init__.py index 1c152c95a..0bacdb303 100644 --- a/griptape/tools/__init__.py +++ b/griptape/tools/__init__.py @@ -26,6 +26,7 @@ from .griptape_cloud_knowledge_base_client.tool import GriptapeCloudKnowledgeBaseClient from .structure_run_client.tool import StructureRunClient from .image_query_client.tool import ImageQueryClient +from .rag_client.tool import RagClient from .text_to_speech_client.tool import TextToSpeechClient from .audio_transcription_client.tool import AudioTranscriptionClient @@ -58,6 +59,7 @@ "GriptapeCloudKnowledgeBaseClient", "StructureRunClient", "ImageQueryClient", + "RagClient", "TextToSpeechClient", "AudioTranscriptionClient", ] diff --git a/griptape/tools/rag_client/__init__.py b/griptape/tools/rag_client/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/tools/rag_client/manifest.yml b/griptape/tools/rag_client/manifest.yml new file mode 100644 index 000000000..86998feb4 --- /dev/null +++ b/griptape/tools/rag_client/manifest.yml @@ -0,0 +1,5 @@ +version: "v1" +name: RAG Client +description: Tool for querying RAG engines +contact_email: hello@griptape.ai +legal_info_url: https://www.griptape.ai/legal \ No newline at end of file diff --git a/griptape/tools/rag_client/requirements.txt b/griptape/tools/rag_client/requirements.txt new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/tools/rag_client/tool.py b/griptape/tools/rag_client/tool.py new file mode 100644 index 000000000..78d716008 --- /dev/null +++ b/griptape/tools/rag_client/tool.py @@ -0,0 +1,38 @@ +from __future__ import annotations +from attrs import define, field +from schema import Schema, Literal +from griptape.artifacts import ErrorArtifact, TextArtifact +from griptape.engines.rag import RagEngine +from griptape.tools import BaseTool +from griptape.utils.decorators import activity + + +@define(kw_only=True) +class RagClient(BaseTool): + """ + Attributes: + description: LLM-friendly RAG engine description. + rag_engine: `RagEngine`. + """ + + description: str = field() + rag_engine: RagEngine = field() + + @activity( + config={ + "description": "{{ _self.description }}", + "schema": Schema({Literal("query", description="A natural language search query"): str}), + } + ) + def search(self, params: dict) -> TextArtifact | ErrorArtifact: + query = params["values"]["query"] + + try: + result = self.rag_engine.process_query(query) + + if result.output is None: + return ErrorArtifact("query output is empty") + else: + return result.output + except Exception as e: + return ErrorArtifact(f"error querying: {e}") diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index f2dc785b0..38d7784c2 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -1,8 +1,10 @@ +from __future__ import annotations from typing import Optional -from griptape.engines import VectorQueryEngine -from schema import Schema, Literal from attrs import define, field -from griptape.artifacts import BaseArtifact, ErrorArtifact +from schema import Schema, Literal +from griptape.artifacts import ErrorArtifact +from griptape.artifacts import ListArtifact +from griptape.drivers import BaseVectorStoreDriver from griptape.tools import BaseTool from griptape.utils.decorators import activity @@ -13,14 +15,14 @@ class VectorStoreClient(BaseTool): Attributes: description: LLM-friendly vector DB description. namespace: Vector storage namespace. - query_engine: `BaseQueryEngine`. + vector_store_driver: `BaseVectorStoreDriver`. top_n: Max number of results returned for the query engine query. """ DEFAULT_TOP_N = 5 description: str = field(kw_only=True) - query_engine: VectorQueryEngine = field(kw_only=True) + vector_store_driver: BaseVectorStoreDriver = field(kw_only=True) top_n: int = field(default=DEFAULT_TOP_N, kw_only=True) namespace: Optional[str] = field(default=None, kw_only=True) @@ -36,10 +38,12 @@ class VectorStoreClient(BaseTool): ), } ) - def search(self, params: dict) -> BaseArtifact: + def search(self, params: dict) -> ListArtifact | ErrorArtifact: query = params["values"]["query"] try: - return self.query_engine.query(query, top_n=self.top_n, namespace=self.namespace) + entries = self.vector_store_driver.query(query, namespace=self.namespace, count=self.top_n) + + return ListArtifact([e.to_artifact() for e in entries]) except Exception as e: return ErrorArtifact(f"error querying vector store: {e}") diff --git a/griptape/utils/__init__.py b/griptape/utils/__init__.py index daac63f4e..5ca129993 100644 --- a/griptape/utils/__init__.py +++ b/griptape/utils/__init__.py @@ -6,6 +6,7 @@ from .command_runner import CommandRunner from .chat import Chat from .futures import execute_futures_dict +from .futures import execute_futures_list from .token_counter import TokenCounter from .prompt_stack import PromptStack from .dict_utils import remove_null_values_in_dict_recursively, dict_merge @@ -35,6 +36,7 @@ def minify_json(value: str) -> str: "import_optional_dependency", "is_dependency_installed", "execute_futures_dict", + "execute_futures_list", "TokenCounter", "PromptStack", "remove_null_values_in_dict_recursively", diff --git a/griptape/utils/futures.py b/griptape/utils/futures.py index 55a4e5d55..d69f4ea48 100644 --- a/griptape/utils/futures.py +++ b/griptape/utils/futures.py @@ -8,3 +8,9 @@ def execute_futures_dict(fs_dict: dict[str, futures.Future[T]]) -> dict[str, T]: futures.wait(fs_dict.values(), timeout=None, return_when=futures.ALL_COMPLETED) return {key: future.result() for key, future in fs_dict.items()} + + +def execute_futures_list(fs_list: list[futures.Future[T]]) -> list[T]: + futures.wait(fs_list, timeout=None, return_when=futures.ALL_COMPLETED) + + return [future.result() for future in fs_list] diff --git a/mkdocs.yml b/mkdocs.yml index 317409c55..337b75f31 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -93,7 +93,8 @@ nav: - Overview: "griptape-framework/tools/index.md" - Building Custom Tools: "griptape-tools/custom-tools/index.md" - Engines: - - Query Engines: "griptape-framework/engines/query-engines.md" + - RAG Engines: "griptape-framework/engines/rag-engines.md" + - Image Query Engines: "griptape-framework/engines/image-query-engines.md" - Extraction Engines: "griptape-framework/engines/extraction-engines.md" - Summary Engines: "griptape-framework/engines/summary-engines.md" - Image Generation Engines: "griptape-framework/engines/image-generation-engines.md" @@ -111,6 +112,7 @@ nav: - Structure Run Drivers: "griptape-framework/drivers/structure-run-drivers.md" - Text to Speech Drivers: "griptape-framework/drivers/text-to-speech-drivers.md" - Audio Transcription Drivers: "griptape-framework/drivers/audio-transcription-drivers.md" + - Web Search Drivers: "griptape-framework/drivers/web-search-drivers.md" - Data: - Overview: "griptape-framework/data/index.md" - Artifacts: "griptape-framework/data/artifacts.md" @@ -149,6 +151,7 @@ nav: - TextToSpeechClient: "griptape-tools/official-tools/text-to-speech-client.md" - AudioTranscriptionClient: "griptape-tools/official-tools/audio-transcription-client.md" - GriptapeCloudKnowledgeBaseClient: "griptape-tools/official-tools/griptape-cloud-knowledge-base-client.md" + - RagClient: "griptape-tools/official-tools/rag-client.md" - Custom Tools: - Building Custom Tools: "griptape-tools/custom-tools/index.md" - Recipes: diff --git a/poetry.lock b/poetry.lock index b71ad227b..1b70d0c93 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3311,6 +3311,7 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ + {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4abe7fef64914ccfa909bc2ba39739670ecc9e820c83ccc7a6ed414122599b83"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1"}, ] @@ -4534,6 +4535,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -6296,6 +6298,7 @@ drivers-prompt-google = ["google-generativeai"] drivers-prompt-huggingface = ["huggingface-hub", "transformers"] drivers-prompt-huggingface-pipeline = ["huggingface-hub", "torch", "transformers"] drivers-prompt-ollama = ["ollama"] +drivers-rerank-cohere = ["cohere"] drivers-sql-postgres = ["pgvector", "psycopg2-binary"] drivers-sql-redshift = ["boto3", "sqlalchemy-redshift"] drivers-sql-snowflake = ["snowflake-sqlalchemy"] @@ -6318,4 +6321,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "ea8512a93be36ad1076915c5751167e3088b035deab1650182f72b842c5f8372" +content-hash = "a5e1a9aaf0fa253d904eee8803dab5f943be59c872c2449b73aea917ecb1c543" diff --git a/pyproject.toml b/pyproject.toml index 377ba46f9..972f0fe81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,6 +104,8 @@ drivers-event-listener-amazon-sqs = ["boto3"] drivers-event-listener-amazon-iot = ["boto3"] drivers-event-listener-pusher = ["pusher"] +drivers-rerank-cohere = ["cohere"] + loaders-dataframe = ["pandas"] loaders-pdf = ["pypdf"] loaders-image = ["pillow"] diff --git a/tests/integration/tasks/test_text_query_task.py b/tests/integration/tasks/test_rag_task.py similarity index 65% rename from tests/integration/tasks/test_text_query_task.py rename to tests/integration/tasks/test_rag_task.py index beb478b33..c0383002c 100644 --- a/tests/integration/tasks/test_text_query_task.py +++ b/tests/integration/tasks/test_rag_task.py @@ -1,8 +1,10 @@ +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.utils.defaults import rag_engine from tests.utils.structure_tester import StructureTester import pytest -class TestTextQueryTask: +class TestRagTask: @pytest.fixture( autouse=True, params=StructureTester.TEXT_SUMMARY_TASK_CAPABLE_PROMPT_DRIVERS, @@ -10,22 +12,18 @@ class TestTextQueryTask: ) def structure_tester(self, request): from griptape.structures import Agent - from griptape.tasks import TextQueryTask + from griptape.tasks import RagTask from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver - from griptape.engines import VectorQueryEngine from griptape.artifacts import TextArtifact vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) - artifact = TextArtifact("John Doe works as as software engineer at Griptape.") + rag_engine_instance = rag_engine(MockPromptDriver(), vector_store_driver) - vector_query_engine = VectorQueryEngine(prompt_driver=request.param, vector_store_driver=vector_store_driver) - vector_query_engine.upsert_text_artifact(artifact=artifact) + vector_store_driver.upsert_text_artifact(artifact=artifact) agent = Agent(prompt_driver=request.param) - agent.add_task( - TextQueryTask("Respond to the users following query: {{ args[0] }}", query_engine=vector_query_engine) - ) + agent.add_task(RagTask("Respond to the users following query: {{ args[0] }}", rag_engine=rag_engine_instance)) return StructureTester(agent) diff --git a/tests/unit/config/test_amazon_bedrock_structure_config.py b/tests/unit/config/test_amazon_bedrock_structure_config.py index d13f103cb..d75684829 100644 --- a/tests/unit/config/test_amazon_bedrock_structure_config.py +++ b/tests/unit/config/test_amazon_bedrock_structure_config.py @@ -92,13 +92,13 @@ def test_to_dict_with_values(self, config_with_values): }, "image_query_driver": { "type": "AmazonBedrockImageQueryDriver", - "model": "anthropic.claude-3-sonnet-20240229-v1:0", + "model": "anthropic.claude-3-5-sonnet-20240620-v1:0", "max_tokens": 256, "image_query_model_driver": {"type": "BedrockClaudeImageQueryModelDriver"}, }, "prompt_driver": { "max_tokens": None, - "model": "anthropic.claude-3-sonnet-20240229-v1:0", + "model": "anthropic.claude-3-5-sonnet-20240620-v1:0", "stream": False, "temperature": 0.1, "type": "AmazonBedrockPromptDriver", diff --git a/tests/unit/drivers/rerank/__init__.py b/tests/unit/drivers/rerank/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/drivers/rerank/test_cohere_rerank_driver.py b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py new file mode 100644 index 000000000..f7b050551 --- /dev/null +++ b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py @@ -0,0 +1,19 @@ +from unittest.mock import Mock +import pytest +from griptape.artifacts import TextArtifact +from griptape.drivers import CohereRerankDriver + + +class TestCohereRerankDriver: + @pytest.fixture + def mock_client(self, mocker): + mock_client = mocker.patch("cohere.Client").return_value + mock_client.rerank.return_value.results = [Mock(), Mock()] + + return mock_client + + def test_run(self, mock_client): + driver = CohereRerankDriver(api_key="api-key") + result = driver.run("hello", artifacts=[TextArtifact("foo"), TextArtifact("bar")]) + + assert len(result) == 2 diff --git a/tests/unit/drivers/vector/test_local_vector_store_driver.py b/tests/unit/drivers/vector/base_local_vector_store_driver.py similarity index 62% rename from tests/unit/drivers/vector/test_local_vector_store_driver.py rename to tests/unit/drivers/vector/base_local_vector_store_driver.py index 8def2c94f..07cf284f8 100644 --- a/tests/unit/drivers/vector/test_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/base_local_vector_store_driver.py @@ -1,21 +1,24 @@ +from abc import ABC, abstractmethod import pytest from griptape.artifacts import TextArtifact, BaseArtifact -from griptape.drivers import LocalVectorStoreDriver -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -class TestLocalVectorStoreDriver: +class BaseLocalVectorStoreDriver(ABC): @pytest.fixture - def driver(self): - return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + @abstractmethod + def driver(self): ... def test_upsert(self, driver): - namespace = driver.upsert_text_artifact(TextArtifact("foobar")) + namespace = driver.upsert_text_artifact(TextArtifact(id="foo1", value="foobar")) assert len(driver.entries) == 1 assert list(driver.entries.keys())[0] == namespace - driver.upsert_text_artifact(TextArtifact("foobar")) + driver.upsert_text_artifact(TextArtifact(id="foo1", value="foobar")) + + assert len(driver.entries) == 1 + + driver.upsert_text_artifact(TextArtifact(id="foo2", value="foobar2")) assert len(driver.entries) == 2 @@ -26,8 +29,8 @@ def test_upsert_multiple(self, driver): bar_entries = driver.load_entries("bar") assert len(driver.entries) == 2 - assert BaseArtifact.from_json(foo_entries[0].meta["artifact"]).value == "foo" - assert BaseArtifact.from_json(bar_entries[0].meta["artifact"]).value == "bar" + assert foo_entries[0].to_artifact().value == "foo" + assert bar_entries[0].to_artifact().value == "bar" def test_query(self, driver): vector_id = driver.upsert_text_artifact(TextArtifact("foobar"), namespace="test-namespace") @@ -37,7 +40,7 @@ def test_query(self, driver): assert len(driver.query("foobar", namespace="test-namespace")) == 1 assert driver.query("foobar")[0].vector == [] assert driver.query("foobar", include_vectors=True)[0].vector == [0, 1] - assert BaseArtifact.from_json(driver.query("foobar")[0].meta["artifact"]).value == "foobar" + assert driver.query("foobar")[0].to_artifact().value == "foobar" assert driver.query("foobar")[0].id == vector_id def test_load_entry(self, driver): @@ -53,3 +56,12 @@ def test_load_entries(self, driver): assert len(driver.load_entries()) == 3 assert len(driver.load_entries("test-namespace-1")) == 2 assert len(driver.load_entries("test-namespace-2")) == 1 + + def test_load_artifacts(self, driver): + driver.upsert_text_artifact(TextArtifact("foobar 1"), namespace="test-namespace-1") + driver.upsert_text_artifact(TextArtifact("foobar 2"), namespace="test-namespace-1") + driver.upsert_text_artifact(TextArtifact("foobar 3"), namespace="test-namespace-2") + + assert len(driver.load_artifacts()) == 3 + assert len(driver.load_artifacts("test-namespace-1")) == 2 + assert len(driver.load_artifacts("test-namespace-2")) == 1 diff --git a/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py b/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py index 53fce635e..b68486914 100644 --- a/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py @@ -40,8 +40,8 @@ def test_upsert_text(self, driver): def test_query(self, driver, monkeypatch): mock_query_result = [ - BaseVectorStoreDriver.QueryResult("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), - BaseVectorStoreDriver.QueryResult("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), ] monkeypatch.setattr(AzureMongoDbVectorStoreDriver, "query", lambda *args, **kwargs: mock_query_result) @@ -52,7 +52,7 @@ def test_query(self, driver, monkeypatch): for result, expected in zip(results, mock_query_result): assert result.id == expected.id assert result.vector == expected.vector - assert isinstance(result, BaseVectorStoreDriver.QueryResult) + assert isinstance(result, BaseVectorStoreDriver.Entry) def test_load_entry(self, driver): vector_id_str = "123" diff --git a/tests/unit/drivers/vector/test_entry.py b/tests/unit/drivers/vector/test_entry.py new file mode 100644 index 000000000..56ee468e1 --- /dev/null +++ b/tests/unit/drivers/vector/test_entry.py @@ -0,0 +1,12 @@ +from griptape.artifacts import TextArtifact +from griptape.drivers import BaseVectorStoreDriver + + +class TestEntry: + def test_from_dict(self): + entry_dict = {"id": "test", "vector": [], "meta": {"artifact": TextArtifact("foo").to_json()}} + assert BaseVectorStoreDriver.Entry.from_dict(entry_dict).id == "test" + + def test_to_artifact(self): + entry = BaseVectorStoreDriver.Entry(id="test", vector=[], meta={"artifact": TextArtifact("foo").to_json()}) + assert entry.to_artifact().value == "foo" diff --git a/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py b/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py new file mode 100644 index 000000000..c426ea5b4 --- /dev/null +++ b/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py @@ -0,0 +1,10 @@ +import pytest +from griptape.drivers import LocalVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.unit.drivers.vector.base_local_vector_store_driver import BaseLocalVectorStoreDriver + + +class TestInMemoryLocalVectorStoreDriver(BaseLocalVectorStoreDriver): + @pytest.fixture + def driver(self): + return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) diff --git a/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py b/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py index 28cddcfbc..5b9aeed06 100644 --- a/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py @@ -40,8 +40,8 @@ def test_upsert_text(self, driver): def test_query(self, driver, monkeypatch): mock_query_result = [ - BaseVectorStoreDriver.QueryResult("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), - BaseVectorStoreDriver.QueryResult("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), ] monkeypatch.setattr(MongoDbAtlasVectorStoreDriver, "query", lambda *args, **kwargs: mock_query_result) @@ -52,7 +52,7 @@ def test_query(self, driver, monkeypatch): for result, expected in zip(results, mock_query_result): assert result.id == expected.id assert result.vector == expected.vector - assert isinstance(result, BaseVectorStoreDriver.QueryResult) + assert isinstance(result, BaseVectorStoreDriver.Entry) def test_load_entry(self, driver): vector_id_str = "123" diff --git a/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py new file mode 100644 index 000000000..1f800967a --- /dev/null +++ b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py @@ -0,0 +1,29 @@ +import os +import tempfile +import pytest +from griptape.artifacts import TextArtifact, BaseArtifact +from griptape.drivers import LocalVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.unit.drivers.vector.base_local_vector_store_driver import BaseLocalVectorStoreDriver + + +class TestPersistentLocalVectorStoreDriver(BaseLocalVectorStoreDriver): + @pytest.fixture + def temp_dir(self): + with tempfile.TemporaryDirectory() as temp_dir: + yield temp_dir + + @pytest.fixture + def driver(self, temp_dir): + persist_file = os.path.join(temp_dir, "store.json") + + return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver(), persist_file=persist_file) + + def test_persistence(self, driver, temp_dir): + persist_file = os.path.join(temp_dir, "store.json") + + driver.upsert_text_artifact(TextArtifact("persistent foobar")) + + new_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver(), persist_file=persist_file) + + assert new_driver.query("persistent foobar")[0].to_artifact().value == "persistent foobar" diff --git a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py index defbe8e3b..c0477fe97 100644 --- a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py +++ b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py @@ -1,4 +1,6 @@ import pytest + +from griptape import utils from griptape.artifacts import TextArtifact from griptape.drivers import PineconeVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -32,7 +34,7 @@ def driver(self): def test_upsert_text_artifact(self, driver): artifact = TextArtifact("foo") - assert driver.upsert_text_artifact(artifact) == artifact.id + assert driver.upsert_text_artifact(artifact) == utils.str_to_hash(artifact.value) def test_upsert_vector(self, driver): assert driver.upsert_vector([0, 1, 2], vector_id="foo") == "foo" diff --git a/tests/unit/engines/query/test_vector_query_engine.py b/tests/unit/engines/query/test_vector_query_engine.py deleted file mode 100644 index 17bde6888..000000000 --- a/tests/unit/engines/query/test_vector_query_engine.py +++ /dev/null @@ -1,58 +0,0 @@ -import pytest -from griptape.artifacts import TextArtifact, BaseArtifact -from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine -from griptape.loaders import TextLoader -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver -from tests.unit.chunkers.utils import gen_paragraph - -MAX_TOKENS = 50 - - -class TestVectorQueryEngine: - @pytest.fixture - def engine(self): - return VectorQueryEngine( - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - prompt_driver=MockPromptDriver(), - ) - - def test_query(self, engine): - artifacts = TextLoader(max_tokens=MAX_TOKENS).load( - gen_paragraph(MAX_TOKENS, engine.prompt_driver.tokenizer, ". ") - ) - - [engine.upsert_text_artifact(a) for a in artifacts] - - assert engine.query("foo").value.startswith("mock output") - - def test_upsert_text_artifact(self, engine): - engine.upsert_text_artifact(TextArtifact("foobar"), namespace="test") - - assert BaseArtifact.from_json(engine.vector_store_driver.load_entries()[0].meta["artifact"]).value == "foobar" - - def test_prompt_creation(self, engine): - system_message = engine.system_template_generator.render( - rulesets=["*RULESET*"], metadata="*META*", text_segments=["*TEXT SEGMENT 1*", "*TEXT SEGMENT 2*"] - ) - user_message = engine.user_template_generator.render(query="*QUESTION*") - - assert "*RULESET*" in system_message - - assert "*META*" in system_message - assert "*QUESTION*" in user_message - assert "*TEXT SEGMENT 1*" in system_message - assert "*TEXT SEGMENT 2*" in system_message - - def test_upsert_text_artifacts(self, engine): - engine.upsert_text_artifacts(artifacts=[TextArtifact("foobar1"), TextArtifact("foobar2")], namespace="test") - - assert BaseArtifact.from_json(engine.vector_store_driver.load_entries()[0].meta["artifact"]).value == "foobar1" - assert BaseArtifact.from_json(engine.vector_store_driver.load_entries()[1].meta["artifact"]).value == "foobar2" - - def test_load_artifacts(self, engine): - engine.upsert_text_artifacts(artifacts=[TextArtifact("foobar1"), TextArtifact("foobar2")], namespace="test") - - assert len(engine.load_artifacts("doesntexist")) == 0 - assert len(engine.load_artifacts("test")) == 2 diff --git a/tests/unit/engines/rag/__init__.py b/tests/unit/engines/rag/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/__init__.py b/tests/unit/engines/rag/modules/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/generation/__init__.py b/tests/unit/engines/rag/modules/generation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py b/tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py new file mode 100644 index 000000000..0bd9f1f85 --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py @@ -0,0 +1,14 @@ +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import MetadataGenerationRagModule + + +class TestMetadataGenerationModule: + def test_run(self): + module = MetadataGenerationRagModule() + + assert "foo" in module.run(RagContext(metadata="foo", initial_query="test")).before_query[0] + + def test_run_with_override(self): + module = MetadataGenerationRagModule(metadata="bar") + + assert "bar" in module.run(RagContext(metadata="foo", initial_query="test")).before_query[0] diff --git a/tests/unit/engines/rag/modules/generation/test_prompt_generation_rag_module.py b/tests/unit/engines/rag/modules/generation/test_prompt_generation_rag_module.py new file mode 100644 index 000000000..0227e2783 --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_prompt_generation_rag_module.py @@ -0,0 +1,25 @@ +import pytest +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import PromptGenerationRagModule +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestPromptGenerationRagModule: + @pytest.fixture + def module(self): + return PromptGenerationRagModule(prompt_driver=MockPromptDriver()) + + def test_run(self, module): + assert module.run(RagContext(initial_query="test")).output.value == "mock output" + + def test_prompt(self, module): + system_message = module.default_system_template_generator( + text_chunks=["*TEXT SEGMENT 1*", "*TEXT SEGMENT 2*"], + before_system_prompt=["*RULESET*", "*META*"], + after_system_prompt=[], + ) + + assert "*RULESET*" in system_message + assert "*META*" in system_message + assert "*TEXT SEGMENT 1*" in system_message + assert "*TEXT SEGMENT 2*" in system_message diff --git a/tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py b/tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py new file mode 100644 index 000000000..6e0fe725a --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py @@ -0,0 +1,10 @@ +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import RulesetsGenerationRagModule +from griptape.rules import Ruleset, Rule + + +class TestRulesetsGenerationRagModule: + def test_run(self): + module = RulesetsGenerationRagModule(rulesets=[Ruleset(name="test ruleset", rules=[Rule("test rule")])]) + + assert "test rule" in module.run(RagContext(initial_query="test")).before_query[0] diff --git a/tests/unit/engines/rag/modules/query/__init__.py b/tests/unit/engines/rag/modules/query/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py b/tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py new file mode 100644 index 000000000..699d73de5 --- /dev/null +++ b/tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py @@ -0,0 +1,13 @@ +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import RelatedQueryGenerationRagModule +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestRelatedQueryGenerationRagModule: + def test_run(self): + result = RelatedQueryGenerationRagModule(prompt_driver=MockPromptDriver(), query_count=10).run( + RagContext(initial_query="test") + ) + + assert len(result) == 10 + assert all(r == "mock output" for r in result) diff --git a/tests/unit/engines/rag/modules/retrieval/__init__.py b/tests/unit/engines/rag/modules/retrieval/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_rerank_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_rerank_rag_module.py new file mode 100644 index 000000000..dc3e46a0a --- /dev/null +++ b/tests/unit/engines/rag/modules/retrieval/test_text_rerank_rag_module.py @@ -0,0 +1,20 @@ +from unittest.mock import Mock +import pytest +from griptape.drivers import CohereRerankDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import TextRerankRagModule + + +class TestTextRerankRagModule: + @pytest.fixture + def mock_client(self, mocker): + mock_client = mocker.patch("cohere.Client").return_value + mock_client.rerank.return_value.results = [Mock(), Mock()] + + return mock_client + + def test_run(self, mock_client): + module = TextRerankRagModule(rerank_driver=CohereRerankDriver(api_key="api-key")) + result = module.run(RagContext(initial_query="test")) + + assert len(result) == 2 diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py new file mode 100644 index 000000000..5b69012d1 --- /dev/null +++ b/tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py @@ -0,0 +1,20 @@ +from griptape.artifacts import TextArtifact +from griptape.drivers import LocalVectorStoreDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import TextRetrievalRagModule +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver + + +class TestTextRetrievalRagModule: + def test_run(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + module = TextRetrievalRagModule(vector_store_driver=vector_store_driver) + + vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") + vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") + + result = module.run(RagContext(initial_query="test")) + + assert len(result) == 2 + assert result[0].value == "foobar1" + assert result[1].value == "foobar2" diff --git a/tests/unit/engines/rag/test_rag_engine.py b/tests/unit/engines/rag/test_rag_engine.py new file mode 100644 index 000000000..b03ab9a1c --- /dev/null +++ b/tests/unit/engines/rag/test_rag_engine.py @@ -0,0 +1,30 @@ +import pytest +from griptape.drivers import LocalVectorStoreDriver +from griptape.engines.rag import RagEngine, RagContext +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestRagEngine: + @pytest.fixture + def engine(self): + return RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + TextRetrievalRagModule( + vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + ) + ] + ), + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule(prompt_driver=MockPromptDriver()) + ), + ) + + def test_process_query(self, engine): + assert engine.process_query("test").output.value == "mock output" + + def test_process(self, engine): + assert engine.process(RagContext(initial_query="test")).output.value == "mock output" diff --git a/tests/unit/memory/tool/test_task_memory.py b/tests/unit/memory/tool/test_task_memory.py index ad7401fbb..fc1cf75c7 100644 --- a/tests/unit/memory/tool/test_task_memory.py +++ b/tests/unit/memory/tool/test_task_memory.py @@ -83,7 +83,7 @@ def test_load_artifacts_for_text_list_artifact(self, memory): memory.process_output( MockTool().test, ActionsSubtask(), - ListArtifact([TextArtifact("foo", name="test1"), TextArtifact("foo", name="test2")], name="test"), + ListArtifact([TextArtifact("foo1", name="test1"), TextArtifact("foo2", name="test2")], name="test"), ) assert len(memory.load_artifacts("test")) == 2 diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index e6c2a1f01..37c8da5a6 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -80,9 +80,11 @@ def test_embedding_driver(self): embedding_driver = MockEmbeddingDriver() agent = Agent(tools=[MockTool()], embedding_driver=embedding_driver) - artifact_storage = list(agent.task_memory.artifact_storages.values())[0] - assert isinstance(artifact_storage, TextArtifactStorage) - memory_embedding_driver = artifact_storage.query_engine.vector_store_driver.embedding_driver + storage = list(agent.task_memory.artifact_storages.values())[0] + assert isinstance(storage, TextArtifactStorage) + memory_embedding_driver = storage.rag_engine.retrieval_stage.retrieval_modules[ + 0 + ].vector_store_driver.embedding_driver assert memory_embedding_driver == embedding_driver @@ -236,8 +238,11 @@ def test_task_memory_defaults(self): storage = list(agent.task_memory.artifact_storages.values())[0] assert isinstance(storage, TextArtifactStorage) - assert storage.query_engine.prompt_driver == prompt_driver - assert storage.query_engine.vector_store_driver.embedding_driver == embedding_driver + assert storage.rag_engine.generation_stage.generation_module.prompt_driver == prompt_driver + assert ( + storage.rag_engine.retrieval_stage.retrieval_modules[0].vector_store_driver.embedding_driver + == embedding_driver + ) assert isinstance(storage.summary_engine, PromptSummaryEngine) assert storage.summary_engine.prompt_driver == prompt_driver assert storage.csv_extraction_engine.prompt_driver == prompt_driver diff --git a/tests/unit/structures/test_pipeline.py b/tests/unit/structures/test_pipeline.py index 8c1cd8511..098709f0e 100644 --- a/tests/unit/structures/test_pipeline.py +++ b/tests/unit/structures/test_pipeline.py @@ -94,7 +94,9 @@ def test_embedding_driver(self): storage = list(pipeline.task_memory.artifact_storages.values())[0] assert isinstance(storage, TextArtifactStorage) - memory_embedding_driver = storage.query_engine.vector_store_driver.embedding_driver + memory_embedding_driver = storage.rag_engine.retrieval_stage.retrieval_modules[ + 0 + ].vector_store_driver.embedding_driver assert memory_embedding_driver == embedding_driver diff --git a/tests/unit/structures/test_workflow.py b/tests/unit/structures/test_workflow.py index bbcf5138e..2646c7b43 100644 --- a/tests/unit/structures/test_workflow.py +++ b/tests/unit/structures/test_workflow.py @@ -108,7 +108,9 @@ def test_embedding_driver(self): storage = list(workflow.task_memory.artifact_storages.values())[0] assert isinstance(storage, TextArtifactStorage) - memory_embedding_driver = storage.query_engine.vector_store_driver.embedding_driver + memory_embedding_driver = storage.rag_engine.retrieval_stage.retrieval_modules[ + 0 + ].vector_store_driver.embedding_driver assert memory_embedding_driver == embedding_driver diff --git a/tests/unit/tasks/test_rag_task.py b/tests/unit/tasks/test_rag_task.py new file mode 100644 index 000000000..75e5007ad --- /dev/null +++ b/tests/unit/tasks/test_rag_task.py @@ -0,0 +1,35 @@ +import pytest +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import PromptGenerationRagModule +from griptape.engines.rag.stages import GenerationRagStage +from griptape.structures import Agent +from griptape.tasks import RagTask +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestRagTask: + @pytest.fixture + def task(self): + return RagTask( + input="test", + rag_engine=RagEngine( + generation_stage=GenerationRagStage( + generation_module=PromptGenerationRagModule(prompt_driver=MockPromptDriver()) + ) + ), + ) + + def test_run(self, task): + agent = Agent() + + agent.add_task(task) + + assert task.run().to_text() == "mock output" + + def test_context_propagation(self, task): + task._input = "{{ test }}" + task.context = {"test": "test value"} + + Agent().add_task(task) + + assert task.input.to_text() == "test value" diff --git a/tests/unit/tasks/test_text_query_task.py b/tests/unit/tasks/test_text_query_task.py deleted file mode 100644 index 6ab0524be..000000000 --- a/tests/unit/tasks/test_text_query_task.py +++ /dev/null @@ -1,48 +0,0 @@ -from tests.mocks.mock_structure_config import MockStructureConfig -import pytest -from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine -from griptape.structures import Agent -from griptape.tasks import TextQueryTask -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver - - -class TestTextQueryTask: - @pytest.fixture - def task(self): - return TextQueryTask( - "test", - query_engine=VectorQueryEngine( - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - prompt_driver=MockPromptDriver(), - ), - namespace="test", - ) - - def test_run(self, task): - agent = Agent() - - agent.add_task(task) - - assert task.run().to_text() == "mock output" - - def test_context_propagation(self, task): - task._input = "{{ test }}" - task.context = {"test": "test value"} - - Agent().add_task(task) - - assert task.input.to_text() == "test value" - - def test_config_query_engine(self, task): - Agent(config=MockStructureConfig()).add_task(task) - - assert isinstance(task.query_engine, VectorQueryEngine) - assert isinstance(task.query_engine.prompt_driver, MockPromptDriver) - - def test_missing_summary_engine(self): - task = TextQueryTask("test") - - with pytest.raises(ValueError): - task.query_engine diff --git a/tests/unit/tasks/test_toolkit_task.py b/tests/unit/tasks/test_toolkit_task.py index f63b06d5b..28cc56ec9 100644 --- a/tests/unit/tasks/test_toolkit_task.py +++ b/tests/unit/tasks/test_toolkit_task.py @@ -1,11 +1,6 @@ -import pytest from griptape.artifacts import ErrorArtifact, TextArtifact -from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine from griptape.structures import Agent from griptape.tasks import ToolkitTask, ActionsSubtask, PromptTask -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tool.tool import MockTool from tests.mocks.mock_value_prompt_driver import MockValuePromptDriver from tests.utils import defaults @@ -141,13 +136,6 @@ class TestToolkitSubtask: "$schema": "http://json-schema.org/draft-07/schema#", } - @pytest.fixture - def query_engine(self): - return VectorQueryEngine( - prompt_driver=MockPromptDriver(), - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - ) - def test_init(self): assert len(ToolkitTask("test", tools=[MockTool(name="Tool1"), MockTool(name="Tool2")]).tools) == 2 @@ -279,7 +267,7 @@ def test_find_tool(self): assert task.find_tool(tool.name) == tool - def test_find_memory(self, query_engine): + def test_find_memory(self): m1 = defaults.text_task_memory("Memory1") m2 = defaults.text_task_memory("Memory2") @@ -291,7 +279,7 @@ def test_find_memory(self, query_engine): assert task.find_memory("Memory1") == m1 assert task.find_memory("Memory2") == m2 - def test_memory(self, query_engine): + def test_memory(self): tool1 = MockTool( name="Tool1", output_memory={"test": [defaults.text_task_memory("Memory1"), defaults.text_task_memory("Memory2")]}, diff --git a/tests/unit/tools/test_rag_client.py b/tests/unit/tools/test_rag_client.py new file mode 100644 index 000000000..9c6497b02 --- /dev/null +++ b/tests/unit/tools/test_rag_client.py @@ -0,0 +1,13 @@ +from griptape.drivers import LocalVectorStoreDriver +from griptape.tools import RagClient +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.utils.defaults import rag_engine + + +class TestRagClient: + def test_search(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool = RagClient(description="Test", rag_engine=rag_engine(MockPromptDriver(), vector_store_driver)) + + assert tool.search({"values": {"query": "test"}}).value == "mock output" diff --git a/tests/unit/tools/test_vector_store_client.py b/tests/unit/tools/test_vector_store_client.py index ef54ed024..9503501b5 100644 --- a/tests/unit/tools/test_vector_store_client.py +++ b/tests/unit/tools/test_vector_store_client.py @@ -1,26 +1,19 @@ import pytest from griptape.artifacts import TextArtifact from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine from griptape.tools import VectorStoreClient from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver class TestVectorStoreClient: @pytest.fixture(autouse=True) - def mock_try_runt(self, mocker): - mocker.patch("griptape.drivers.OpenAiChatPromptDriver.try_run", return_value=TextArtifact("foobar")) - + def mock_try_run(self, mocker): mocker.patch("griptape.drivers.OpenAiEmbeddingDriver.try_embed_chunk", return_value=[0, 1]) def test_search(self): - tool = VectorStoreClient( - description="Test", - query_engine=VectorQueryEngine( - prompt_driver=MockPromptDriver(mock_output="foobar"), - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - ), - ) + driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool = VectorStoreClient(description="Test", vector_store_driver=driver) + + driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) - assert tool.search({"values": {"query": "test"}}).value == "foobar" + assert set([a.value for a in tool.search({"values": {"query": "test"}})]) == {"foo", "bar"} diff --git a/tests/unit/utils/test_futures.py b/tests/unit/utils/test_futures.py index d50416f58..5e30148a9 100644 --- a/tests/unit/utils/test_futures.py +++ b/tests/unit/utils/test_futures.py @@ -12,5 +12,14 @@ def test_execute_futures_dict(self): assert result["foo"] == "foo-bar" assert result["baz"] == "baz-bar" + def test_execute_futures_list(self): + with futures.ThreadPoolExecutor() as executor: + result = utils.execute_futures_list( + [executor.submit(self.foobar, "foo"), executor.submit(self.foobar, "baz")] + ) + + assert result[0] == "foo-bar" + assert result[1] == "baz-bar" + def foobar(self, foo): return f"{foo}-bar" diff --git a/tests/utils/defaults.py b/tests/utils/defaults.py index 801eed7de..f27410308 100644 --- a/tests/utils/defaults.py +++ b/tests/utils/defaults.py @@ -1,6 +1,9 @@ from griptape.artifacts import TextArtifact, BlobArtifact from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine, PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine +from griptape.engines import PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule +from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage from griptape.memory import TaskMemory from griptape.memory.task.storage import TextArtifactStorage, BlobArtifactStorage from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -8,11 +11,11 @@ def text_tool_artifact_storage(): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + return TextArtifactStorage( - query_engine=VectorQueryEngine( - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - prompt_driver=MockPromptDriver(), - ), + rag_engine=rag_engine(MockPromptDriver(), vector_store_driver), + vector_store_driver=vector_store_driver, summary_engine=PromptSummaryEngine(prompt_driver=MockPromptDriver()), csv_extraction_engine=CsvExtractionEngine(prompt_driver=MockPromptDriver()), json_extraction_engine=JsonExtractionEngine(prompt_driver=MockPromptDriver()), @@ -23,3 +26,12 @@ def text_task_memory(name): return TaskMemory( name=name, artifact_storages={TextArtifact: text_tool_artifact_storage(), BlobArtifact: BlobArtifactStorage()} ) + + +def rag_engine(prompt_driver, vector_store_driver): + return RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[TextRetrievalRagModule(vector_store_driver=vector_store_driver)] + ), + generation_stage=GenerationRagStage(generation_module=PromptGenerationRagModule(prompt_driver=prompt_driver)), + ) From 095d12f9d458f283375920a4bc65f8d81e1fc4e8 Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Mon, 24 Jun 2024 11:55:02 -0700 Subject: [PATCH 11/87] Change GriptapeCloudKnowledgeBaseClient to use /search API (#888) --- CHANGELOG.md | 1 + griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e920f5a5e..710a1c76f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: Merged `BaseVectorStoreDriver.QueryResult` into `BaseVectorStoreDriver.Entry`. - **BREAKING**: Replaced `query_engine` with `vector_store_driver` in `VectorStoreClient`. - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. +- `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. ## [0.27.1] - 2024-06-20 diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 6fed6e618..7c94cda5d 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -31,7 +31,7 @@ def query(self, params: dict) -> TextArtifact | ErrorArtifact: from requests import post, exceptions query = params["values"]["query"] - url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") + url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/search") try: response = post(url, json={"query": query}, headers=self.headers) From 9010fdc7e30cf1d1501013c560d53e917ec0029e Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Mon, 24 Jun 2024 12:45:31 -0700 Subject: [PATCH 12/87] `meta` parameter added to TextArtifact (#891) --- CHANGELOG.md | 1 + griptape/artifacts/text_artifact.py | 3 ++- tests/unit/artifacts/test_text_artifact.py | 8 ++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 710a1c76f..435b62505 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `DuckDuckGoWebSearchDriver` to web search with the DuckDuckGo search SDK. - `ProxyWebScraperDriver` to web scrape using proxies. - Parameter `session` on `AmazonBedrockStructureConfig`. +- Parameter `meta` on `TextArtifact`. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. diff --git a/griptape/artifacts/text_artifact.py b/griptape/artifacts/text_artifact.py index e8a2bb2a7..8b83303f0 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, Any, Optional from attrs import define, field from griptape.artifacts import BaseArtifact @@ -13,6 +13,7 @@ class TextArtifact(BaseArtifact): value: str = field(converter=str, metadata={"serializable": True}) encoding: str = field(default="utf-8", kw_only=True) encoding_error_handler: str = field(default="strict", kw_only=True) + meta: dict[str, Any] = field(factory=dict, kw_only=True, metadata={"serializable": True}) _embedding: list[float] = field(factory=list, kw_only=True) @property diff --git a/tests/unit/artifacts/test_text_artifact.py b/tests/unit/artifacts/test_text_artifact.py index f913429d7..6ea2c6697 100644 --- a/tests/unit/artifacts/test_text_artifact.py +++ b/tests/unit/artifacts/test_text_artifact.py @@ -61,3 +61,11 @@ def test_name(self): assert artifact.name == artifact.id assert TextArtifact("foo", name="bar").name == "bar" + + def test_meta(self): + artifact = TextArtifact("foo") + + assert artifact.meta == {} + + meta = {"foo": "bar"} + assert TextArtifact("foo", meta=meta).meta == meta From c2575f5318fccb7d11efd83d909ec248e9a7a28e Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Tue, 25 Jun 2024 08:05:38 -0700 Subject: [PATCH 13/87] Handle error on vector entry not existing (#893) --- griptape/drivers/vector/base_vector_store_driver.py | 5 ++++- ...re_driver.py => test_base_local_vector_store_driver.py} | 7 ++++++- .../vector/test_in_memory_local_vector_store_driver.py | 2 +- .../vector/test_persistent_local_vector_store_driver.py | 4 ++-- 4 files changed, 13 insertions(+), 5 deletions(-) rename tests/unit/drivers/vector/{base_local_vector_store_driver.py => test_base_local_vector_store_driver.py} (91%) diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 71f1c1061..b1d9ed6d0 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -92,7 +92,10 @@ def upsert_text( ) def does_entry_exist(self, vector_id: str, namespace: Optional[str] = None) -> bool: - return self.load_entry(vector_id, namespace) is not None + try: + return self.load_entry(vector_id, namespace) is not None + except Exception: + return False def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: result = self.load_entries(namespace) diff --git a/tests/unit/drivers/vector/base_local_vector_store_driver.py b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py similarity index 91% rename from tests/unit/drivers/vector/base_local_vector_store_driver.py rename to tests/unit/drivers/vector/test_base_local_vector_store_driver.py index 07cf284f8..c34a54d98 100644 --- a/tests/unit/drivers/vector/base_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod import pytest -from griptape.artifacts import TextArtifact, BaseArtifact +from unittest.mock import patch +from griptape.artifacts import TextArtifact class BaseLocalVectorStoreDriver(ABC): @@ -65,3 +66,7 @@ def test_load_artifacts(self, driver): assert len(driver.load_artifacts()) == 3 assert len(driver.load_artifacts("test-namespace-1")) == 2 assert len(driver.load_artifacts("test-namespace-2")) == 1 + + def test_does_entry_exist_exception(self, driver): + with patch.object(driver, "load_entry", side_effect=Exception): + assert driver.does_entry_exist("does_not_exist") is False diff --git a/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py b/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py index c426ea5b4..cb8fcbefe 100644 --- a/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py @@ -1,7 +1,7 @@ import pytest from griptape.drivers import LocalVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.unit.drivers.vector.base_local_vector_store_driver import BaseLocalVectorStoreDriver +from tests.unit.drivers.vector.test_base_local_vector_store_driver import BaseLocalVectorStoreDriver class TestInMemoryLocalVectorStoreDriver(BaseLocalVectorStoreDriver): diff --git a/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py index 1f800967a..8f6773fc1 100644 --- a/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py @@ -1,10 +1,10 @@ import os import tempfile import pytest -from griptape.artifacts import TextArtifact, BaseArtifact +from griptape.artifacts import TextArtifact from griptape.drivers import LocalVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.unit.drivers.vector.base_local_vector_store_driver import BaseLocalVectorStoreDriver +from tests.unit.drivers.vector.test_base_local_vector_store_driver import BaseLocalVectorStoreDriver class TestPersistentLocalVectorStoreDriver(BaseLocalVectorStoreDriver): From 2df58d551963d214892642bc6645b407d45d2219 Mon Sep 17 00:00:00 2001 From: Emily Danielson <2302515+emjay07@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:56:09 -0700 Subject: [PATCH 14/87] Bumping gemini to latest version (#892) --- poetry.lock | 92 +++++++++++++++++++++++++++++++++++++++++++++----- pyproject.toml | 2 +- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1b70d0c93..e030c8906 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "aiohttp" @@ -1543,17 +1543,18 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "google-ai-generativelanguage" -version = "0.4.0" +version = "0.6.5" description = "Google Ai Generativelanguage API client library" optional = true python-versions = ">=3.7" files = [ - {file = "google-ai-generativelanguage-0.4.0.tar.gz", hash = "sha256:c8199066c08f74c4e91290778329bb9f357ba1ea5d6f82de2bc0d10552bf4f8c"}, - {file = "google_ai_generativelanguage-0.4.0-py3-none-any.whl", hash = "sha256:e4c425376c1ee26c78acbc49a24f735f90ebfa81bf1a06495fae509a2433232c"}, + {file = "google-ai-generativelanguage-0.6.5.tar.gz", hash = "sha256:c4089c277fa4e26722f76ab03ee3039f28be8bf1c9be282948b9583a154c6d79"}, + {file = "google_ai_generativelanguage-0.6.5-py3-none-any.whl", hash = "sha256:236875bb4a6d6ebdba2f12bd9d5e776100fd913402157a47b5e9fb80a13f25a7"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" @@ -1588,6 +1589,24 @@ grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +[[package]] +name = "google-api-python-client" +version = "2.134.0" +description = "Google API Client Library for Python" +optional = true +python-versions = ">=3.7" +files = [ + {file = "google-api-python-client-2.134.0.tar.gz", hash = "sha256:4a8f0bea651a212997cc83c0f271fc86f80ef93d1cee9d84de7dfaeef2a858b6"}, + {file = "google_api_python_client-2.134.0-py2.py3-none-any.whl", hash = "sha256:ba05d60f6239990b7994f6328f17bb154c602d31860fb553016dc9f8ce886945"}, +] + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0" +google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" +google-auth-httplib2 = ">=0.2.0,<1.0.0" +httplib2 = ">=0.19.0,<1.dev0" +uritemplate = ">=3.0.1,<5" + [[package]] name = "google-auth" version = "2.29.0" @@ -1611,19 +1630,35 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] +[[package]] +name = "google-auth-httplib2" +version = "0.2.0" +description = "Google Authentication Library: httplib2 transport" +optional = true +python-versions = "*" +files = [ + {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, + {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, +] + +[package.dependencies] +google-auth = "*" +httplib2 = ">=0.19.0" + [[package]] name = "google-generativeai" -version = "0.4.1" +version = "0.7.0" description = "Google Generative AI High level API client library and tools." optional = true python-versions = ">=3.9" files = [ - {file = "google_generativeai-0.4.1-py3-none-any.whl", hash = "sha256:89be3c00c2e688108fccefc50f47f45fc9d37ecd53c1ade9d86b5d982919c24a"}, + {file = "google_generativeai-0.7.0-py3-none-any.whl", hash = "sha256:7be4b634afeb8b6bebde1af7271e94d2af84d2d28b5988c7ed9921733c40fe63"}, ] [package.dependencies] -google-ai-generativelanguage = "0.4.0" +google-ai-generativelanguage = "0.6.5" google-api-core = "*" +google-api-python-client = "*" google-auth = ">=2.15.0" protobuf = "*" pydantic = "*" @@ -1863,6 +1898,20 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] trio = ["trio (>=0.22.0,<0.26.0)"] +[[package]] +name = "httplib2" +version = "0.22.0" +description = "A comprehensive HTTP client library." +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, + {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, +] + +[package.dependencies] +pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} + [[package]] name = "httpx" version = "0.27.0" @@ -4242,6 +4291,20 @@ cryptography = ">=41.0.5,<43" docs = ["sphinx (!=5.2.0,!=5.2.0.post0,!=7.2.5)", "sphinx-rtd-theme"] test = ["pretend", "pytest (>=3.0.1)", "pytest-rerunfailures"] +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = true +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + [[package]] name = "pypdf" version = "3.17.4" @@ -5944,6 +6007,17 @@ tzdata = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] +[[package]] +name = "uritemplate" +version = "4.1.1" +description = "Implementation of RFC 6570 URI Templates" +optional = true +python-versions = ">=3.6" +files = [ + {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, + {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, +] + [[package]] name = "urllib3" version = "1.26.18" @@ -6321,4 +6395,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a5e1a9aaf0fa253d904eee8803dab5f943be59c872c2449b73aea917ecb1c543" +content-hash = "ce26764ee2c4a9a99d24ef4afc7efa6aa894a7560a725388ff24db15f6014e9a" diff --git a/pyproject.toml b/pyproject.toml index 972f0fe81..29d4fda44 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ redis = { version = "^4.6.0", optional = true } opensearch-py = { version = "^2.3.1", optional = true } pgvector = { version = "^0.2.3", optional = true } psycopg2-binary = { version = "^2.9.9", optional = true } -google-generativeai = { version = "^0.4.1", optional = true } +google-generativeai = { version = "^0.7.0", optional = true } trafilatura = {version = "^1.6", optional = true} playwright = {version = "^1.42", optional = true} beautifulsoup4 = {version = "^4.12.3", optional = true} From 80c27cb1fff80a4d3c9200f6a95db28c59de71ca Mon Sep 17 00:00:00 2001 From: Vasily Vasinov Date: Tue, 25 Jun 2024 15:06:43 -0600 Subject: [PATCH 15/87] VectorStoreClient improvements (#899) --- CHANGELOG.md | 4 +++ .../official-tools/vector-store-client.md | 2 +- griptape/tools/vector_store_client/tool.py | 30 +++++++++---------- tests/unit/tools/test_vector_store_client.py | 25 +++++++++++++++- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 435b62505..818211d8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ProxyWebScraperDriver` to web scrape using proxies. - Parameter `session` on `AmazonBedrockStructureConfig`. - Parameter `meta` on `TextArtifact`. +- `VectorStoreClient` improvements: + - `VectorStoreClient.query_params` dict for custom query params. + - `VectorStoreClient.process_query_output_fn` for custom query output processing logic. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. @@ -46,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: Merged `BaseVectorStoreDriver.QueryResult` into `BaseVectorStoreDriver.Entry`. - **BREAKING**: Replaced `query_engine` with `vector_store_driver` in `VectorStoreClient`. - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. +- **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. - `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. ## [0.27.1] - 2024-06-20 diff --git a/docs/griptape-tools/official-tools/vector-store-client.md b/docs/griptape-tools/official-tools/vector-store-client.md index ffdbbba91..f3cab2065 100644 --- a/docs/griptape-tools/official-tools/vector-store-client.md +++ b/docs/griptape-tools/official-tools/vector-store-client.md @@ -21,7 +21,7 @@ vector_store_driver.upsert_text_artifacts( vector_db = VectorStoreClient( description="This DB has information about the Griptape Python framework", vector_store_driver=vector_store_driver, - namespace="griptape", + query_params={"namespace": "griptape"}, off_prompt=True ) diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index 38d7784c2..8d4e73022 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -1,34 +1,36 @@ from __future__ import annotations -from typing import Optional -from attrs import define, field +from typing import Callable, Any +from attrs import define, field, Factory from schema import Schema, Literal -from griptape.artifacts import ErrorArtifact +from griptape.artifacts import ErrorArtifact, BaseArtifact from griptape.artifacts import ListArtifact from griptape.drivers import BaseVectorStoreDriver from griptape.tools import BaseTool from griptape.utils.decorators import activity -@define +@define(kw_only=True) class VectorStoreClient(BaseTool): """ Attributes: description: LLM-friendly vector DB description. - namespace: Vector storage namespace. vector_store_driver: `BaseVectorStoreDriver`. - top_n: Max number of results returned for the query engine query. + query_params: Optional dictionary of vector store driver query parameters. + process_query_output_fn: Optional lambda for processing vector store driver query output `Entry`s. """ DEFAULT_TOP_N = 5 - description: str = field(kw_only=True) - vector_store_driver: BaseVectorStoreDriver = field(kw_only=True) - top_n: int = field(default=DEFAULT_TOP_N, kw_only=True) - namespace: Optional[str] = field(default=None, kw_only=True) + description: str = field() + vector_store_driver: BaseVectorStoreDriver = field() + query_params: dict[str, Any] = field(factory=dict) + process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], BaseArtifact] = field( + default=Factory(lambda: lambda es: ListArtifact([e.to_artifact() for e in es])) + ) @activity( config={ - "description": "Can be used to search a vector database with the following description: {{ _self.description }}", + "description": "Can be used to search a database with the following description: {{ _self.description }}", "schema": Schema( { Literal( @@ -38,12 +40,10 @@ class VectorStoreClient(BaseTool): ), } ) - def search(self, params: dict) -> ListArtifact | ErrorArtifact: + def search(self, params: dict) -> BaseArtifact: query = params["values"]["query"] try: - entries = self.vector_store_driver.query(query, namespace=self.namespace, count=self.top_n) - - return ListArtifact([e.to_artifact() for e in entries]) + return self.process_query_output_fn(self.vector_store_driver.query(query, **self.query_params)) except Exception as e: return ErrorArtifact(f"error querying vector store: {e}") diff --git a/tests/unit/tools/test_vector_store_client.py b/tests/unit/tools/test_vector_store_client.py index 9503501b5..45018b847 100644 --- a/tests/unit/tools/test_vector_store_client.py +++ b/tests/unit/tools/test_vector_store_client.py @@ -1,5 +1,5 @@ import pytest -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, ListArtifact from griptape.drivers import LocalVectorStoreDriver from griptape.tools import VectorStoreClient from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -17,3 +17,26 @@ def test_search(self): driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) assert set([a.value for a in tool.search({"values": {"query": "test"}})]) == {"foo", "bar"} + + def test_search_with_namespace(self): + driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool1 = VectorStoreClient(description="Test", vector_store_driver=driver, query_params={"namespace": "test"}) + tool2 = VectorStoreClient(description="Test", vector_store_driver=driver, query_params={"namespace": "test2"}) + + driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) + + assert len(tool1.search({"values": {"query": "test"}})) == 2 + assert len(tool2.search({"values": {"query": "test"}})) == 0 + + def test_custom_process_query_output_fn(self): + driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool1 = VectorStoreClient( + description="Test", + vector_store_driver=driver, + process_query_output_fn=lambda es: ListArtifact([e.vector for e in es]), + query_params={"include_vectors": True}, + ) + + driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) + + assert tool1.search({"values": {"query": "test"}}).value == [[0, 1], [0, 1]] From 22981b12529eadb96842d601e7eedf99d9d1bf6d Mon Sep 17 00:00:00 2001 From: Vasily Vasinov Date: Tue, 25 Jun 2024 15:19:37 -0600 Subject: [PATCH 16/87] Wrap future execution with context managers (#898) --- CHANGELOG.md | 1 + .../drivers/vector/base_vector_store_driver.py | 15 ++++++++------- .../related_query_generation_rag_module.py | 17 +++++++++-------- .../retrieval/text_retrieval_rag_module.py | 13 +++++++------ griptape/engines/rag/stages/query_rag_stage.py | 9 +++++---- .../engines/rag/stages/retrieval_rag_stage.py | 5 ++--- griptape/loaders/base_loader.py | 11 +++++------ griptape/tasks/actions_subtask.py | 5 ++--- griptape/utils/file_utils.py | 7 ++++--- 9 files changed, 43 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 818211d8f..d1e581b4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. - **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. - `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. +- Wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. ## [0.27.1] - 2024-06-20 diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index b1d9ed6d0..8002101b7 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -36,13 +36,14 @@ def to_artifact(self) -> BaseArtifact: def upsert_text_artifacts( self, artifacts: dict[str, list[TextArtifact]], meta: Optional[dict] = None, **kwargs ) -> None: - utils.execute_futures_dict( - { - namespace: self.futures_executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) - for namespace, artifact_list in artifacts.items() - for a in artifact_list - } - ) + with self.futures_executor as executor: + utils.execute_futures_dict( + { + namespace: executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) + for namespace, artifact_list in artifacts.items() + for a in artifact_list + } + ) def upsert_text_artifact( self, diff --git a/griptape/engines/rag/modules/query/related_query_generation_rag_module.py b/griptape/engines/rag/modules/query/related_query_generation_rag_module.py index 4661e24a2..9f610c0e5 100644 --- a/griptape/engines/rag/modules/query/related_query_generation_rag_module.py +++ b/griptape/engines/rag/modules/query/related_query_generation_rag_module.py @@ -18,14 +18,15 @@ class RelatedQueryGenerationRagModule(BaseQueryRagModule): def run(self, context: RagContext) -> list[str]: system_prompt = self.generate_system_template(context.initial_query) - results = utils.execute_futures_list( - [ - self.futures_executor.submit( - self.prompt_driver.run, self.generate_query_prompt_stack(system_prompt, "Alternative query: ") - ) - for _ in range(self.query_count) - ] - ) + with self.futures_executor as executor: + results = utils.execute_futures_list( + [ + executor.submit( + self.prompt_driver.run, self.generate_query_prompt_stack(system_prompt, "Alternative query: ") + ) + for _ in range(self.query_count) + ] + ) return [r.value for r in results] diff --git a/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py index 5c6bedac4..1434b9880 100644 --- a/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py @@ -21,12 +21,13 @@ def run(self, context: RagContext) -> Sequence[TextArtifact]: all_queries = [context.initial_query] + context.alternative_queries namespace = self.namespace or context.namespace - results = utils.execute_futures_list( - [ - self.futures_executor.submit(self.vector_store_driver.query, query, self.top_n, namespace, False) - for query in all_queries - ] - ) + with self.futures_executor as executor: + results = utils.execute_futures_list( + [ + executor.submit(self.vector_store_driver.query, query, self.top_n, namespace, False) + for query in all_queries + ] + ) return [ artifact diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py index b122fa7a6..8c93ad763 100644 --- a/griptape/engines/rag/stages/query_rag_stage.py +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -14,10 +14,11 @@ class QueryRagStage(BaseRagStage): def run(self, context: RagContext) -> RagContext: logging.info(f"QueryStage: running {len(self.query_generation_modules)} query generation modules in parallel") - results = utils.execute_futures_list( - [self.futures_executor.submit(r.run, context) for r in self.query_generation_modules] - ) + with self.futures_executor as executor: + results = utils.execute_futures_list( + [executor.submit(r.run, context) for r in self.query_generation_modules] + ) - context.alternative_queries = list(itertools.chain.from_iterable(results)) + context.alternative_queries = list(itertools.chain.from_iterable(results)) return context diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py index 8a0ceca44..77443fb2f 100644 --- a/griptape/engines/rag/stages/retrieval_rag_stage.py +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -19,9 +19,8 @@ class RetrievalRagStage(BaseRagStage): def run(self, context: RagContext) -> RagContext: logging.info(f"RetrievalStage: running {len(self.retrieval_modules)} retrieval modules in parallel") - results = utils.execute_futures_list( - [self.futures_executor.submit(r.run, context) for r in self.retrieval_modules] - ) + with self.futures_executor as executor: + results = utils.execute_futures_list([executor.submit(r.run, context) for r in self.retrieval_modules]) # flatten the list of lists results = list(itertools.chain.from_iterable(results)) diff --git a/griptape/loaders/base_loader.py b/griptape/loaders/base_loader.py index 1648b8f26..40121067c 100644 --- a/griptape/loaders/base_loader.py +++ b/griptape/loaders/base_loader.py @@ -26,12 +26,11 @@ def load_collection( # Create a dictionary before actually submitting the jobs to the executor # to avoid duplicate work. sources_by_key = {self.to_key(source): source for source in sources} - return execute_futures_dict( - { - key: self.futures_executor.submit(self.load, source, *args, **kwargs) - for key, source in sources_by_key.items() - } - ) + + with self.futures_executor as executor: + return execute_futures_dict( + {key: executor.submit(self.load, source, *args, **kwargs) for key, source in sources_by_key.items()} + ) def to_key(self, source: Any, *args, **kwargs) -> str: if isinstance(source, bytes): diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index 1546a825d..ae3893abb 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -119,9 +119,8 @@ def run(self) -> BaseArtifact: return ErrorArtifact("no tool output") def execute_actions(self, actions: list[Action]) -> list[tuple[str, BaseArtifact]]: - results = utils.execute_futures_dict( - {a.tag: self.futures_executor.submit(self.execute_action, a) for a in actions} - ) + with self.futures_executor as executor: + results = utils.execute_futures_dict({a.tag: executor.submit(self.execute_action, a) for a in actions}) return [r for r in results.values()] diff --git a/griptape/utils/file_utils.py b/griptape/utils/file_utils.py index 402436a2f..ebe5ba456 100644 --- a/griptape/utils/file_utils.py +++ b/griptape/utils/file_utils.py @@ -30,6 +30,7 @@ def load_files(paths: list[str], futures_executor: Optional[futures.ThreadPoolEx if futures_executor is None: futures_executor = futures.ThreadPoolExecutor() - return utils.execute_futures_dict( - {utils.str_to_hash(str(path)): futures_executor.submit(load_file, path) for path in paths} - ) + with futures_executor as executor: + return utils.execute_futures_dict( + {utils.str_to_hash(str(path)): executor.submit(load_file, path) for path in paths} + ) From 2a347f32ed1ce948ce4e1bf8654c13640ee342a5 Mon Sep 17 00:00:00 2001 From: Emily Danielson <2302515+emjay07@users.noreply.github.com> Date: Tue, 25 Jun 2024 15:39:12 -0700 Subject: [PATCH 17/87] Bug Fix: Cohere prompts with no history (#900) --- CHANGELOG.md | 1 + .../drivers/prompt-drivers.md | 2 +- docs/griptape-framework/structures/config.md | 13 ++++++ .../drivers/prompt/cohere_prompt_driver.py | 12 ++++-- .../prompt/test_cohere_prompt_driver.py | 41 +++++++++++++++++-- 5 files changed, 61 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1e581b4b..183c3a34a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. - `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. - Wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. +- Fixed bug in `CoherePromptDriver` to properly handle empty history ## [0.27.1] - 2024-06-20 diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index 0100ccbac..96a1be4e1 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -141,7 +141,7 @@ from griptape.config import StructureConfig agent = Agent( config=StructureConfig( prompt_driver=CoherePromptDriver( - model="command", + model="command-r", api_key=os.environ['COHERE_API_KEY'], ) ) diff --git a/docs/griptape-framework/structures/config.md b/docs/griptape-framework/structures/config.md index 1a69d70c0..969163bf6 100644 --- a/docs/griptape-framework/structures/config.md +++ b/docs/griptape-framework/structures/config.md @@ -95,6 +95,19 @@ agent = Agent( ) ``` +#### Cohere + +The [Cohere Structure Config](../../reference/griptape/config/cohere_structure_config.md) provides default Drivers for Cohere's APIs. + + +```python +import os +from griptape.config import CohereStructureConfig +from griptape.structures import Agent + +agent = Agent(config=CohereStructureConfig(api_key=os.environ["COHERE_API_KEY"])) +``` + ### Custom Configs You can create your own [StructureConfig](../../reference/griptape/config/structure_config.md) by overriding relevant Drivers. diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index ca199011a..f4a306ebe 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -52,12 +52,18 @@ def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dic def _base_params(self, prompt_stack: PromptStack) -> dict: user_message = prompt_stack.inputs[-1].content - history_messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs[:-1]] + history_messages = [ + self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs[:-1] if input.content + ] - return { + params = { "message": user_message, - "chat_history": history_messages, "temperature": self.temperature, "stop_sequences": self.tokenizer.stop_sequences, "max_tokens": self.max_tokens, } + + if history_messages: + params["chat_history"] = history_messages + + return params diff --git a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py index b3ceb11a4..6e5063b26 100644 --- a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py @@ -7,16 +7,16 @@ class TestCoherePromptDriver: @pytest.fixture def mock_client(self, mocker): - mock_client = mocker.patch("cohere.Client").return_value - mock_client.chat.return_value = Mock(text="model-output") + mock_client = mocker.patch("cohere.Client") + mock_client.return_value.chat.return_value = Mock(text="model-output") return mock_client @pytest.fixture def mock_stream_client(self, mocker): - mock_client = mocker.patch("cohere.Client").return_value + mock_client = mocker.patch("cohere.Client") mock_chunk = Mock(text="model-output", event_type="text-generation") - mock_client.chat_stream.return_value = iter([mock_chunk]) + mock_client.return_value.chat_stream.return_value = iter([mock_chunk]) return mock_client @@ -42,8 +42,41 @@ def test_try_run(self, mock_client, prompt_stack): # pyright: ignore # When text_artifact = driver.try_run(prompt_stack) + print(f"Called methods: {mock_client}") # Then + expected_message = "assistant-input" + expected_history = [ + {"role": "ASSISTANT", "text": "generic-input"}, + {"role": "SYSTEM", "text": "system-input"}, + {"role": "USER", "text": "user-input"}, + ] + mock_client.return_value.chat.assert_called_once_with( + message=expected_message, + temperature=driver.temperature, + stop_sequences=driver.tokenizer.stop_sequences, + max_tokens=driver.max_tokens, + chat_history=expected_history, + ) + assert text_artifact.value == "model-output" + + def test_try_run_no_history(self, mock_client, prompt_stack): + # Given + prompt_stack_no_history = PromptStack() + prompt_stack_no_history.add_user_input("user-input") + driver = CoherePromptDriver(model="command", api_key="api-key") + + # When + text_artifact = driver.try_run(prompt_stack_no_history) + + # Then + expected_message = "user-input" + mock_client.return_value.chat.assert_called_once_with( + message=expected_message, + temperature=driver.temperature, + stop_sequences=driver.tokenizer.stop_sequences, + max_tokens=driver.max_tokens, + ) assert text_artifact.value == "model-output" def test_try_stream_run(self, mock_stream_client, prompt_stack): # pyright: ignore From 6d08c20a2d50ace70595480cf58a2d54bef678aa Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Thu, 27 Jun 2024 11:19:19 -0500 Subject: [PATCH 18/87] Fix `StructureVisualizer.to_url()` (#903) --- CHANGELOG.md | 5 ++++- griptape/utils/structure_visualizer.py | 6 +++--- tests/unit/utils/test_structure_visualizer.py | 6 +++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 183c3a34a..3d79f92f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,7 +52,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. - `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. - Wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. -- Fixed bug in `CoherePromptDriver` to properly handle empty history + +### Fixed +- `CoherePromptDriver` to properly handle empty history. +- `StructureVisualizer.to_url()` by wrapping task IDs in single quotes. ## [0.27.1] - 2024-06-20 diff --git a/griptape/utils/structure_visualizer.py b/griptape/utils/structure_visualizer.py index ede282761..999519cf1 100644 --- a/griptape/utils/structure_visualizer.py +++ b/griptape/utils/structure_visualizer.py @@ -32,11 +32,11 @@ def to_url(self) -> str: base64_string = base64.b64encode(graph_bytes).decode("utf-8") url = f"https://mermaid.ink/svg/{base64_string}" - return url def __render_task(self, task: BaseTask) -> str: if task.children: - return f'{task.id}--> {" & ".join([child.id for child in task.children])};' + children = " & ".join([f"'{child.id}'" for child in task.children]) + return f"'{task.id}'--> {children};" else: - return f"{task.id};" + return f"'{task.id}';" diff --git a/tests/unit/utils/test_structure_visualizer.py b/tests/unit/utils/test_structure_visualizer.py index d7177bf30..396b81166 100644 --- a/tests/unit/utils/test_structure_visualizer.py +++ b/tests/unit/utils/test_structure_visualizer.py @@ -11,7 +11,7 @@ def test_agent(self): visualizer = StructureVisualizer(agent) result = visualizer.to_url() - assert result == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMTs=" + assert result == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgkndGFzazEnOw==" def test_pipeline(self): pipeline = Pipeline( @@ -29,7 +29,7 @@ def test_pipeline(self): assert ( result - == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMS0tPiB0YXNrMjsKCXRhc2syLS0+IHRhc2szOwoJdGFzazMtLT4gdGFzazQ7Cgl0YXNrNDs=" + == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgkndGFzazEnLS0+ICd0YXNrMic7CgkndGFzazInLS0+ICd0YXNrMyc7CgkndGFzazMnLS0+ICd0YXNrNCc7CgkndGFzazQnOw==" ) def test_workflow(self): @@ -48,5 +48,5 @@ def test_workflow(self): assert ( result - == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMS0tPiB0YXNrMiAmIHRhc2szOwoJdGFzazItLT4gdGFzazQ7Cgl0YXNrMy0tPiB0YXNrNDsKCXRhc2s0Ow==" + == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgkndGFzazEnLS0+ICd0YXNrMicgJiAndGFzazMnOwoJJ3Rhc2syJy0tPiAndGFzazQnOwoJJ3Rhc2szJy0tPiAndGFzazQnOwoJJ3Rhc2s0Jzs=" ) From ef070023ec28de4af8150145ef34048d25f07f77 Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Thu, 27 Jun 2024 13:46:05 -0500 Subject: [PATCH 19/87] Add `fail_fast` parameter to `Structure` (#908) --- CHANGELOG.md | 1 + griptape/structures/agent.py | 6 +++++ griptape/structures/pipeline.py | 2 +- griptape/structures/structure.py | 1 + griptape/structures/workflow.py | 2 +- tests/unit/structures/test_agent.py | 4 +++ tests/unit/structures/test_pipeline.py | 36 ++++++++++++++++++++++++-- tests/unit/structures/test_workflow.py | 12 ++++++++- 8 files changed, 59 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d79f92f8..3de99e54f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `VectorStoreClient` improvements: - `VectorStoreClient.query_params` dict for custom query params. - `VectorStoreClient.process_query_output_fn` for custom query output processing logic. +- Parameter `fail_fast` to `Structure`. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index d0446aff0..2840d5c46 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -15,6 +15,12 @@ class Agent(Structure): input_template: str = field(default=PromptTask.DEFAULT_INPUT_TEMPLATE) tools: list[BaseTool] = field(factory=list, kw_only=True) max_meta_memory_entries: Optional[int] = field(default=20, kw_only=True) + fail_fast: bool = field(default=False, kw_only=True) + + @fail_fast.validator # pyright: ignore + def validate_fail_fast(self, _, fail_fast: bool) -> None: + if fail_fast: + raise ValueError("Agents cannot fail fast, as they can only have 1 task.") def __attrs_post_init__(self) -> None: super().__attrs_post_init__() diff --git a/griptape/structures/pipeline.py b/griptape/structures/pipeline.py index d5724244e..4fc784974 100644 --- a/griptape/structures/pipeline.py +++ b/griptape/structures/pipeline.py @@ -74,7 +74,7 @@ def __run_from_task(self, task: Optional[BaseTask]) -> None: if task is None: return else: - if isinstance(task.execute(), ErrorArtifact): + if isinstance(task.execute(), ErrorArtifact) and self.fail_fast: return else: self.__run_from_task(next(iter(task.children), None)) diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 036e47cc8..c5854ccac 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -62,6 +62,7 @@ class Structure(ABC): default=Factory(lambda self: self.default_task_memory, takes_self=True), kw_only=True ) meta_memory: MetaMemory = field(default=Factory(lambda: MetaMemory()), kw_only=True) + fail_fast: bool = field(default=True, kw_only=True) _execution_args: tuple = () _logger: Optional[Logger] = None diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 6552fba89..dd76597d8 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -108,7 +108,7 @@ def try_run(self, *args) -> Workflow: # Wait for all tasks to complete for future in futures.as_completed(futures_list): - if isinstance(future.result(), ErrorArtifact): + if isinstance(future.result(), ErrorArtifact) and self.fail_fast: exit_loop = True break diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index 37c8da5a6..8bcadb753 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -267,3 +267,7 @@ def finished_tasks(self): agent.run("hello") assert len(agent.finished_tasks) == 1 + + def test_fail_fast(self): + with pytest.raises(ValueError): + Agent(prompt_driver=MockPromptDriver(), fail_fast=True) diff --git a/tests/unit/structures/test_pipeline.py b/tests/unit/structures/test_pipeline.py index 098709f0e..d94616165 100644 --- a/tests/unit/structures/test_pipeline.py +++ b/tests/unit/structures/test_pipeline.py @@ -1,10 +1,11 @@ import pytest +import time -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, ErrorArtifact from griptape.memory.task.storage import TextArtifactStorage from griptape.rules import Rule, Ruleset from griptape.tokenizers import OpenAiTokenizer -from griptape.tasks import PromptTask, BaseTask, ToolkitTask +from griptape.tasks import PromptTask, BaseTask, ToolkitTask, CodeExecutionTask from griptape.memory.structure import ConversationMemory from tests.mocks.mock_prompt_driver import MockPromptDriver from griptape.structures import Pipeline @@ -13,6 +14,21 @@ class TestPipeline: + @pytest.fixture + def waiting_task(self): + def fn(task): + time.sleep(2) + return TextArtifact("done") + + return CodeExecutionTask(run_fn=fn) + + @pytest.fixture + def error_artifact_task(self): + def fn(task): + return ErrorArtifact("error") + + return CodeExecutionTask(run_fn=fn) + def test_init(self): driver = MockPromptDriver() pipeline = Pipeline(prompt_driver=driver, rulesets=[Ruleset("TestRuleset", [Rule("test")])]) @@ -357,3 +373,19 @@ def test_deprecation(self): with pytest.deprecated_call(): Pipeline(stream=True) + + def test_run_with_error_artifact(self, error_artifact_task, waiting_task): + end_task = PromptTask("end") + pipeline = Pipeline(prompt_driver=MockPromptDriver(), tasks=[waiting_task, error_artifact_task, end_task]) + pipeline.run() + + assert pipeline.output is None + + def test_run_with_error_artifact_no_fail_fast(self, error_artifact_task, waiting_task): + end_task = PromptTask("end") + pipeline = Pipeline( + prompt_driver=MockPromptDriver(), tasks=[waiting_task, error_artifact_task, end_task], fail_fast=False + ) + pipeline.run() + + assert pipeline.output is not None diff --git a/tests/unit/structures/test_workflow.py b/tests/unit/structures/test_workflow.py index 2646c7b43..4d44fceb8 100644 --- a/tests/unit/structures/test_workflow.py +++ b/tests/unit/structures/test_workflow.py @@ -17,7 +17,7 @@ class TestWorkflow: @fixture def waiting_task(self): def fn(task): - time.sleep(10) + time.sleep(2) return TextArtifact("done") return CodeExecutionTask(run_fn=fn) @@ -728,6 +728,16 @@ def test_run_with_error_artifact(self, error_artifact_task, waiting_task): assert workflow.output is None + def test_run_with_error_artifact_no_fail_fast(self, error_artifact_task, waiting_task): + end_task = PromptTask("end") + end_task.add_parents([error_artifact_task, waiting_task]) + workflow = Workflow( + prompt_driver=MockPromptDriver(), tasks=[waiting_task, error_artifact_task, end_task], fail_fast=False + ) + workflow.run() + + assert workflow.output is not None + @staticmethod def _validate_topology_1(workflow): assert len(workflow.tasks) == 4 From 3858cdc50c912606f86e1d401ef96d8fdf18e574 Mon Sep 17 00:00:00 2001 From: Emily Danielson <2302515+emjay07@users.noreply.github.com> Date: Thu, 27 Jun 2024 12:14:11 -0700 Subject: [PATCH 20/87] fixing bug for upserting csv artifacts (#909) --- .../drivers/vector/base_vector_store_driver.py | 2 +- .../vector/test_base_local_vector_store_driver.py | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 8002101b7..219406d0b 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -54,7 +54,7 @@ def upsert_text_artifact( **kwargs, ) -> str: meta = {} if meta is None else meta - vector_id = utils.str_to_hash(artifact.value) if vector_id is None else vector_id + vector_id = utils.str_to_hash(artifact.to_text()) if vector_id is None else vector_id if self.does_entry_exist(vector_id, namespace): return vector_id diff --git a/tests/unit/drivers/vector/test_base_local_vector_store_driver.py b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py index c34a54d98..6cd1763f6 100644 --- a/tests/unit/drivers/vector/test_base_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py @@ -2,6 +2,7 @@ import pytest from unittest.mock import patch from griptape.artifacts import TextArtifact +from griptape.artifacts.csv_row_artifact import CsvRowArtifact class BaseLocalVectorStoreDriver(ABC): @@ -23,6 +24,20 @@ def test_upsert(self, driver): assert len(driver.entries) == 2 + def test_upsert_csv_row(self, driver): + namespace = driver.upsert_text_artifact(CsvRowArtifact(id="foo1", value={"col": "value"})) + + assert len(driver.entries) == 1 + assert list(driver.entries.keys())[0] == namespace + + driver.upsert_text_artifact(CsvRowArtifact(id="foo1", value={"col": "value"})) + + assert len(driver.entries) == 1 + + driver.upsert_text_artifact(CsvRowArtifact(id="foo2", value={"col": "value2"})) + + assert len(driver.entries) == 2 + def test_upsert_multiple(self, driver): driver.upsert_text_artifacts({"foo": [TextArtifact("foo")], "bar": [TextArtifact("bar")]}) From 716ae04457020af03150c8083767386a125d2619 Mon Sep 17 00:00:00 2001 From: Andrew French Date: Thu, 27 Jun 2024 14:24:10 -0700 Subject: [PATCH 21/87] [hotfix] Don't add ToolkitTask stop sequence if already present (#906) --- CHANGELOG.md | 5 +++++ griptape/tasks/toolkit_task.py | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a6ef78793..3ca29ab48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.27.2] - 2024-06-27 + +### Fixed +- Avoid adding duplicate Tokenizer stop sequences in a ToolkitTask + ## [0.27.1] - 2024-06-20 ### Added diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index c99f9e23f..61b19b5d3 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -130,7 +130,9 @@ def run(self) -> BaseArtifact: self.subtasks.clear() - self.prompt_driver.tokenizer.stop_sequences.extend([self.response_stop_sequence]) + if self.response_stop_sequence not in self.prompt_driver.tokenizer.stop_sequences: + self.prompt_driver.tokenizer.stop_sequences.extend([self.response_stop_sequence]) + subtask = self.add_subtask(ActionsSubtask(self.prompt_driver.run(prompt_stack=self.prompt_stack).to_text())) while True: From b93f209e458039fcd546e6dbb90a97869259ec2a Mon Sep 17 00:00:00 2001 From: Vasily Vasinov Date: Thu, 27 Jun 2024 15:31:26 -0600 Subject: [PATCH 22/87] All `futures_executor` fields renamed to `futures_executor_fn` and now accept callables instead of futures (#910) --- CHANGELOG.md | 2 +- .../event_listener/base_event_listener_driver.py | 10 +++++----- griptape/drivers/vector/base_vector_store_driver.py | 8 +++++--- griptape/engines/rag/modules/base_rag_module.py | 6 +++++- .../query/related_query_generation_rag_module.py | 2 +- .../rag/modules/retrieval/text_retrieval_rag_module.py | 2 +- griptape/engines/rag/stages/base_rag_stage.py | 5 ++++- griptape/engines/rag/stages/query_rag_stage.py | 2 +- griptape/engines/rag/stages/retrieval_rag_stage.py | 2 +- griptape/loaders/base_loader.py | 8 +++++--- griptape/structures/workflow.py | 8 +++++--- griptape/tasks/actions_subtask.py | 2 +- griptape/tasks/base_task.py | 6 ++++-- 13 files changed, 39 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3de99e54f..1a4655652 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,7 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. - **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. - `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. -- Wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. +- **BREAKING**: All `futures_executor` fields renamed to `futures_executor_fn` and now accept callables instead of futures; wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. ### Fixed - `CoherePromptDriver` to properly handle empty history. diff --git a/griptape/drivers/event_listener/base_event_listener_driver.py b/griptape/drivers/event_listener/base_event_listener_driver.py index b6d2d9b12..17a754b65 100644 --- a/griptape/drivers/event_listener/base_event_listener_driver.py +++ b/griptape/drivers/event_listener/base_event_listener_driver.py @@ -1,11 +1,9 @@ from __future__ import annotations - from abc import ABC, abstractmethod from concurrent import futures from logging import Logger - +from typing import Callable from attrs import Factory, define, field - from griptape.events import BaseEvent logger = Logger(__name__) @@ -13,7 +11,9 @@ @define class BaseEventListenerDriver(ABC): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) batched: bool = field(default=True, kw_only=True) batch_size: int = field(default=10, kw_only=True) @@ -24,7 +24,7 @@ def batch(self) -> list[dict]: return self._batch def publish_event(self, event: BaseEvent | dict, flush: bool = False) -> None: - self.futures_executor.submit(self._safe_try_publish_event, event, flush) + self.futures_executor_fn().submit(self._safe_try_publish_event, event, flush) @abstractmethod def try_publish_event_payload(self, event_payload: dict) -> None: ... diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 219406d0b..2c0962328 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from concurrent import futures from dataclasses import dataclass -from typing import Any +from typing import Any, Callable from typing import Optional from attrs import define, field, Factory from griptape import utils @@ -31,12 +31,14 @@ def to_artifact(self) -> BaseArtifact: return BaseArtifact.from_json(self.meta["artifact"]) # pyright: ignore[reportOptionalSubscript] embedding_driver: BaseEmbeddingDriver = field(kw_only=True, metadata={"serializable": True}) - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) def upsert_text_artifacts( self, artifacts: dict[str, list[TextArtifact]], meta: Optional[dict] = None, **kwargs ) -> None: - with self.futures_executor as executor: + with self.futures_executor_fn() as executor: utils.execute_futures_dict( { namespace: executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py index 958cbd46c..8e9b42e93 100644 --- a/griptape/engines/rag/modules/base_rag_module.py +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -1,5 +1,7 @@ from abc import ABC from concurrent import futures +from typing import Callable + from attrs import define, field, Factory from griptape.utils import PromptStack @@ -7,7 +9,9 @@ @define(kw_only=True) class BaseRagModule(ABC): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor())) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()) + ) def generate_query_prompt_stack(self, system_prompt: str, query: str) -> PromptStack: return PromptStack( diff --git a/griptape/engines/rag/modules/query/related_query_generation_rag_module.py b/griptape/engines/rag/modules/query/related_query_generation_rag_module.py index 9f610c0e5..138e5f034 100644 --- a/griptape/engines/rag/modules/query/related_query_generation_rag_module.py +++ b/griptape/engines/rag/modules/query/related_query_generation_rag_module.py @@ -18,7 +18,7 @@ class RelatedQueryGenerationRagModule(BaseQueryRagModule): def run(self, context: RagContext) -> list[str]: system_prompt = self.generate_system_template(context.initial_query) - with self.futures_executor as executor: + with self.futures_executor_fn() as executor: results = utils.execute_futures_list( [ executor.submit( diff --git a/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py index 1434b9880..9c756bfea 100644 --- a/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py @@ -21,7 +21,7 @@ def run(self, context: RagContext) -> Sequence[TextArtifact]: all_queries = [context.initial_query] + context.alternative_queries namespace = self.namespace or context.namespace - with self.futures_executor as executor: + with self.futures_executor_fn() as executor: results = utils.execute_futures_list( [ executor.submit(self.vector_store_driver.query, query, self.top_n, namespace, False) diff --git a/griptape/engines/rag/stages/base_rag_stage.py b/griptape/engines/rag/stages/base_rag_stage.py index 786975b82..ca19e1bb4 100644 --- a/griptape/engines/rag/stages/base_rag_stage.py +++ b/griptape/engines/rag/stages/base_rag_stage.py @@ -1,12 +1,15 @@ from abc import ABC, abstractmethod from concurrent import futures +from typing import Callable from attrs import define, field, Factory from griptape.engines.rag import RagContext @define(kw_only=True) class BaseRagStage(ABC): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor())) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()) + ) @abstractmethod def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py index 8c93ad763..c2216aea8 100644 --- a/griptape/engines/rag/stages/query_rag_stage.py +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -14,7 +14,7 @@ class QueryRagStage(BaseRagStage): def run(self, context: RagContext) -> RagContext: logging.info(f"QueryStage: running {len(self.query_generation_modules)} query generation modules in parallel") - with self.futures_executor as executor: + with self.futures_executor_fn() as executor: results = utils.execute_futures_list( [executor.submit(r.run, context) for r in self.query_generation_modules] ) diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py index 77443fb2f..cbc90a43e 100644 --- a/griptape/engines/rag/stages/retrieval_rag_stage.py +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -19,7 +19,7 @@ class RetrievalRagStage(BaseRagStage): def run(self, context: RagContext) -> RagContext: logging.info(f"RetrievalStage: running {len(self.retrieval_modules)} retrieval modules in parallel") - with self.futures_executor as executor: + with self.futures_executor_fn() as executor: results = utils.execute_futures_list([executor.submit(r.run, context) for r in self.retrieval_modules]) # flatten the list of lists diff --git a/griptape/loaders/base_loader.py b/griptape/loaders/base_loader.py index 40121067c..00fbf07ec 100644 --- a/griptape/loaders/base_loader.py +++ b/griptape/loaders/base_loader.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from concurrent import futures -from typing import Any, Optional +from typing import Any, Optional, Callable from collections.abc import Mapping, Sequence from attrs import define, field, Factory @@ -14,7 +14,9 @@ @define class BaseLoader(ABC): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) encoding: Optional[str] = field(default=None, kw_only=True) @abstractmethod @@ -27,7 +29,7 @@ def load_collection( # to avoid duplicate work. sources_by_key = {self.to_key(source): source for source in sources} - with self.futures_executor as executor: + with self.futures_executor_fn() as executor: return execute_futures_dict( {key: executor.submit(self.load, source, *args, **kwargs) for key, source in sources_by_key.items()} ) diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index dd76597d8..7e65fbf5a 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -1,7 +1,7 @@ from __future__ import annotations import concurrent.futures as futures from graphlib import TopologicalSorter -from typing import Any, Optional +from typing import Any, Optional, Callable from attrs import define, field, Factory from griptape.artifacts import ErrorArtifact from griptape.structures import Structure @@ -11,7 +11,9 @@ @define class Workflow(Structure): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) @property def output_task(self) -> Optional[BaseTask]: @@ -103,7 +105,7 @@ def try_run(self, *args) -> Workflow: for task in ordered_tasks: if task.can_execute(): - future = self.futures_executor.submit(task.execute) + future = self.futures_executor_fn().submit(task.execute) futures_list[future] = task # Wait for all tasks to complete diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index ae3893abb..fa2aff822 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -119,7 +119,7 @@ def run(self) -> BaseArtifact: return ErrorArtifact("no tool output") def execute_actions(self, actions: list[Action]) -> list[tuple[str, BaseArtifact]]: - with self.futures_executor as executor: + with self.futures_executor_fn() as executor: results = utils.execute_futures_dict({a.tag: executor.submit(self.execute_action, a) for a in actions}) return [r for r in results.values()] diff --git a/griptape/tasks/base_task.py b/griptape/tasks/base_task.py index 8a45cb14e..be5ff94d8 100644 --- a/griptape/tasks/base_task.py +++ b/griptape/tasks/base_task.py @@ -4,7 +4,7 @@ from abc import ABC, abstractmethod from concurrent import futures from enum import Enum -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any, Optional, Callable from attrs import define, field, Factory @@ -33,7 +33,9 @@ class State(Enum): output: Optional[BaseArtifact] = field(default=None, init=False) structure: Optional[Structure] = field(default=None, init=False) context: dict[str, Any] = field(factory=dict, kw_only=True) - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) @property @abstractmethod From 6d1ff76de9ce168eba7e85653a489a85d904cf6b Mon Sep 17 00:00:00 2001 From: Andrew French Date: Thu, 27 Jun 2024 14:47:15 -0700 Subject: [PATCH 23/87] [hotfix] Fix token calculation in VectorQueryEngine (#911) --- CHANGELOG.md | 3 ++- griptape/engines/query/vector_query_engine.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ca29ab48..e1db28e87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.27.2] - 2024-06-27 ### Fixed -- Avoid adding duplicate Tokenizer stop sequences in a ToolkitTask +- Avoid adding duplicate Tokenizer stop sequences in a `ToolkitTask`. +- Fixed token count calculation in `VectorQueryEngine`. ## [0.27.1] - 2024-06-20 diff --git a/griptape/engines/query/vector_query_engine.py b/griptape/engines/query/vector_query_engine.py index 24338b348..de93b5af4 100644 --- a/griptape/engines/query/vector_query_engine.py +++ b/griptape/engines/query/vector_query_engine.py @@ -49,7 +49,7 @@ def query( ) user_message = self.user_template_generator.render(query=query) - message_token_count = self.prompt_driver.tokenizer.count_input_tokens_left( + message_token_count = self.prompt_driver.tokenizer.count_tokens( self.prompt_driver.prompt_stack_to_string( PromptStack( inputs=[ From 6d5feef97886963ca17a600bceddd3cee623edab Mon Sep 17 00:00:00 2001 From: Andrew French Date: Thu, 27 Jun 2024 15:08:30 -0700 Subject: [PATCH 24/87] Version bump v0.27.2 (#912) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1ed9e0d3f..77c4108da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "griptape" -version = "0.27.1" +version = "0.27.2" description = "Modular Python framework for LLM workflows, tools, memory, and data." authors = ["Griptape "] license = "Apache 2.0" From 3ee8c3556a3bcd270088e210ea4fdc12bbf490ab Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Fri, 28 Jun 2024 11:50:03 -0500 Subject: [PATCH 25/87] Add `BooleanArtifact` (#905) --- CHANGELOG.md | 1 + docs/griptape-framework/data/artifacts.md | 19 ++++++---- griptape/artifacts/__init__.py | 2 ++ griptape/artifacts/boolean_artifact.py | 31 ++++++++++++++++ tests/unit/artifacts/test_boolean_artifact.py | 35 +++++++++++++++++++ 5 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 griptape/artifacts/boolean_artifact.py create mode 100644 tests/unit/artifacts/test_boolean_artifact.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a4655652..33824f753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `VectorStoreClient.query_params` dict for custom query params. - `VectorStoreClient.process_query_output_fn` for custom query output processing logic. - Parameter `fail_fast` to `Structure`. +- `BooleanArtifact` for handling boolean values. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. diff --git a/docs/griptape-framework/data/artifacts.md b/docs/griptape-framework/data/artifacts.md index 5b69b120a..6fe77574b 100644 --- a/docs/griptape-framework/data/artifacts.md +++ b/docs/griptape-framework/data/artifacts.md @@ -1,11 +1,11 @@ ## Overview -**Artifacts** are used for passing different types of data between Griptape components. All tools return artifacts that are later consumed by tasks and task memory. +**[Artifacts](../../reference/griptape/artifacts/base_artifact.md)** are used for passing different types of data between Griptape components. All tools return artifacts that are later consumed by tasks and task memory. Artifacts make sure framework components enforce contracts when passing and consuming data. ## TextArtifact -Used for passing text data of arbitrary size around the framework. It can be used to count tokens with [token_count()](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.token_count) with a tokenizer. +A [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) for passing text data of arbitrary size around the framework. It can be used to count tokens with [token_count()](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.token_count) with a tokenizer. It can also be used to generate a text embedding with [generate_embedding()](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.generate_embedding) and access it with [embedding](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.embedding). @@ -13,20 +13,20 @@ and access it with [embedding](../../reference/griptape/artifacts/text_artifact. ## CsvRowArtifact -Used for passing structured row data around the framework. It inherits from [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) and overrides the +A [CsvRowArtifact](../../reference/griptape/artifacts/csv_row_artifact.md) for passing structured row data around the framework. It inherits from [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) and overrides the [to_text()](../../reference/griptape/artifacts/csv_row_artifact.md#griptape.artifacts.csv_row_artifact.CsvRowArtifact.to_text) method, which always returns a valid CSV row. ## InfoArtifact -Used for passing short notifications back to the LLM without task memory storing them. +An [InfoArtifact](../../reference/griptape/artifacts/info_artifact.md) for passing short notifications back to the LLM without task memory storing them. ## ErrorArtifact -Used for passing errors back to the LLM without task memory storing them. +An [ErrorArtifact](../../reference/griptape/artifacts/error_artifact.md) is used for passing errors back to the LLM without task memory storing them. ## BlobArtifact -Used for passing binary large objects (blobs) back to the LLM. +A [BlobArtifact](../../reference/griptape/artifacts/blob_artifact.md) for passing binary large objects (blobs) back to the LLM. Treat it as a way to return unstructured data, such as images, videos, audio, and other files back from tools. Each blob has a [name](../../reference/griptape/artifacts/base_artifact.md#griptape.artifacts.base_artifact.BaseArtifact.name) and [dir](../../reference/griptape/artifacts/blob_artifact.md#griptape.artifacts.blob_artifact.BlobArtifact.dir_name) to uniquely identify stored objects. @@ -40,3 +40,10 @@ An [ImageArtifact](../../reference/griptape/artifacts/image_artifact.md) is used ## AudioArtifact An [AudioArtifact](../../reference/griptape/artifacts/audio_artifact.md) allows the Framework to interact with audio content. An Audio Artifact includes binary audio content as well as metadata like format, duration, and prompt and model information for audio returned generative models. It inherits from [BlobArtifact](#blobartifact). + +## BooleanArtifact + +A [BooleanArtifact](../../reference/griptape/artifacts/boolean_artifact.md) is used for passing boolean values around the framework. + +!!! info + Any object passed on init to `BooleanArtifact` will be coerced into a `bool` type. This might lead to unintended behavior: `BooleanArtifact("False").value is True`. Use [BooleanArtifact.parse_bool](../../reference/griptape/artifacts/boolean_artifact.md#griptape.artifacts.boolean_artifact.BooleanArtifact.parse_bool) to convert case-insensitive string literal values `"True"` and `"False"` into a `BooleanArtifact`: `BooleanArtifact.parse_bool("False").value is False`. diff --git a/griptape/artifacts/__init__.py b/griptape/artifacts/__init__.py index e57177ac4..00c19519f 100644 --- a/griptape/artifacts/__init__.py +++ b/griptape/artifacts/__init__.py @@ -3,6 +3,7 @@ from .info_artifact import InfoArtifact from .text_artifact import TextArtifact from .blob_artifact import BlobArtifact +from .boolean_artifact import BooleanArtifact from .csv_row_artifact import CsvRowArtifact from .list_artifact import ListArtifact from .media_artifact import MediaArtifact @@ -16,6 +17,7 @@ "InfoArtifact", "TextArtifact", "BlobArtifact", + "BooleanArtifact", "CsvRowArtifact", "ListArtifact", "MediaArtifact", diff --git a/griptape/artifacts/boolean_artifact.py b/griptape/artifacts/boolean_artifact.py new file mode 100644 index 000000000..a7a84da18 --- /dev/null +++ b/griptape/artifacts/boolean_artifact.py @@ -0,0 +1,31 @@ +from __future__ import annotations +from typing import Any, Union +from attrs import define, field +from griptape.artifacts import BaseArtifact + + +@define +class BooleanArtifact(BaseArtifact): + value: bool = field(converter=bool, metadata={"serializable": True}) + meta: dict[str, Any] = field(factory=dict, kw_only=True, metadata={"serializable": True}) + + @classmethod + def parse_bool(cls, value: Union[str, bool]) -> BooleanArtifact: + """ + Convert a string literal or bool to a BooleanArtifact. The string must be either "true" or "false" with any casing. + """ + if value is not None: + if isinstance(value, str): + if value.lower() == "true": + return BooleanArtifact(True) + elif value.lower() == "false": + return BooleanArtifact(False) + elif isinstance(value, bool): + return BooleanArtifact(value) + raise ValueError(f"Cannot convert '{value}' to BooleanArtifact") + + def __add__(self, other: BaseArtifact) -> BooleanArtifact: + raise ValueError("Cannot add BooleanArtifact with other artifacts") + + def __eq__(self, value: object) -> bool: + return self.value is value diff --git a/tests/unit/artifacts/test_boolean_artifact.py b/tests/unit/artifacts/test_boolean_artifact.py new file mode 100644 index 000000000..bcad67673 --- /dev/null +++ b/tests/unit/artifacts/test_boolean_artifact.py @@ -0,0 +1,35 @@ +import pytest +from griptape.artifacts import BooleanArtifact + + +class TestBooleanArtifact: + def test_parse_bool(self): + assert BooleanArtifact.parse_bool("true").value is True + assert BooleanArtifact.parse_bool("false").value is False + assert BooleanArtifact.parse_bool("True").value is True + assert BooleanArtifact.parse_bool("False").value is False + + with pytest.raises(ValueError): + BooleanArtifact.parse_bool("foo") + + with pytest.raises(ValueError): + BooleanArtifact.parse_bool(None) + + assert BooleanArtifact.parse_bool(True).value is True + assert BooleanArtifact.parse_bool(False).value is False + + def test_add(self): + with pytest.raises(ValueError): + BooleanArtifact(True) + BooleanArtifact(True) + + def test_value_type_conversion(self): + assert BooleanArtifact(1).value is True + assert BooleanArtifact(0).value is False + assert BooleanArtifact(True).value is True + assert BooleanArtifact(False).value is False + assert BooleanArtifact("true").value is True + assert BooleanArtifact("false").value is True + assert BooleanArtifact([1]).value is True + assert BooleanArtifact([]).value is False + assert BooleanArtifact(False) == False + assert BooleanArtifact(True) == True From becdc1dfeffe9883190a4b8e1ba9a054eb4dd7fd Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 1 Jul 2024 17:23:23 -0500 Subject: [PATCH 26/87] Add pull request template (#921) --- .github/pull_request_template.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..3a3496ef6 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,8 @@ +## Describe your changes + +## Issue ticket number and link + +## Checklist before requesting a review +- [ ] I have performed a self-review of my code. +- [ ] I have added thorough tests. +- [ ] Is this a notable change? If so, please update the [changelog](https://github.com/griptape-ai/griptape/blob/dev/CHANGELOG.md). From 1cd558852372aa6ff6a5a25a73fccf4f049fc6f3 Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Mon, 1 Jul 2024 15:48:59 -0700 Subject: [PATCH 27/87] Fix missing parent error handling in Workflow task insertion (#856) Co-authored-by: Collin Dutter --- CHANGELOG.md | 1 + griptape/structures/workflow.py | 10 +++++-- tests/unit/structures/test_workflow.py | 38 ++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33824f753..ddb48c4f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -133,6 +133,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Streaming not working when using deprecated `Structure.stream` field. - Raw Tool output being lost when being executed by ActionsSubtask. - Re-order Workflow tasks on every task execution wave. +- `Workflow.insert_task()` enumerates by parent id equality, opposed to object equality. - Web Loader to catch Exceptions and properly return an ErrorArtifact. - Conversation Memory entry only added if `output_task.output` is not `None` on all `Structures` - `TextArtifacts` contained in `ListArtifact` returned by `WebSearch.search` to properly formatted stringified JSON. diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 7e65fbf5a..204650c41 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -87,9 +87,13 @@ def insert_task( if task.id not in parent_task.child_ids: parent_task.child_ids.append(task.id) - parent_index = self.tasks.index(parent_task) - if parent_index > last_parent_index: - last_parent_index = parent_index + try: + parent_index = self.tasks.index(parent_task) + except ValueError: + raise ValueError(f"Parent task {parent_task.id} not found in workflow.") + else: + if parent_index > last_parent_index: + last_parent_index = parent_index # Insert the new task once, just after the last parent task self.tasks.insert(last_parent_index + 1, task) diff --git a/tests/unit/structures/test_workflow.py b/tests/unit/structures/test_workflow.py index 4d44fceb8..2b89684d3 100644 --- a/tests/unit/structures/test_workflow.py +++ b/tests/unit/structures/test_workflow.py @@ -351,6 +351,44 @@ def test_run_topology_1_imperative_insert(self): self._validate_topology_1(workflow) + def test_run_topology_1_missing_parent(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + workflow = Workflow(prompt_driver=MockPromptDriver()) + + # task1 never added to workflow + workflow + task4 + with pytest.raises(ValueError): + workflow.insert_tasks(task1, [task2, task3], task4) + + def test_run_topology_1_id_equality(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + workflow = Workflow(prompt_driver=MockPromptDriver()) + + # task4 never added to workflow + workflow + task1 + workflow.insert_tasks(task1, [task2, task3], task4) + + with pytest.raises(ValueError): + workflow.run() + + def test_run_topology_1_object_equality(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + workflow = Workflow(prompt_driver=MockPromptDriver()) + + workflow + task1 + workflow + task4 + with pytest.raises(ValueError): + workflow.insert_tasks(PromptTask("test1", id="task1"), [task2, task3], task4) + def test_run_topology_2_declarative_parents(self): workflow = Workflow( prompt_driver=MockPromptDriver(), From f8be8ee6078938fa51838fd658bf1d0acae6f861 Mon Sep 17 00:00:00 2001 From: dylanholmes <4370153+dylanholmes@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:35:00 -0700 Subject: [PATCH 28/87] Ensure Executor.shutdown() called after task submission in BaseEventListenerDriver.publish_event() (#919) --- .../event_listener/base_event_listener_driver.py | 3 ++- .../test_base_event_listener_driver.py | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/griptape/drivers/event_listener/base_event_listener_driver.py b/griptape/drivers/event_listener/base_event_listener_driver.py index 17a754b65..b433ed755 100644 --- a/griptape/drivers/event_listener/base_event_listener_driver.py +++ b/griptape/drivers/event_listener/base_event_listener_driver.py @@ -24,7 +24,8 @@ def batch(self) -> list[dict]: return self._batch def publish_event(self, event: BaseEvent | dict, flush: bool = False) -> None: - self.futures_executor_fn().submit(self._safe_try_publish_event, event, flush) + with self.futures_executor_fn() as executor: + executor.submit(self._safe_try_publish_event, event, flush) @abstractmethod def try_publish_event_payload(self, event_payload: dict) -> None: ... diff --git a/tests/unit/drivers/event_listener/test_base_event_listener_driver.py b/tests/unit/drivers/event_listener/test_base_event_listener_driver.py index 6d33dd2a0..383c0be89 100644 --- a/tests/unit/drivers/event_listener/test_base_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_base_event_listener_driver.py @@ -1,8 +1,20 @@ +from unittest.mock import MagicMock from tests.mocks.mock_event import MockEvent from tests.mocks.mock_event_listener_driver import MockEventListenerDriver class TestBaseEventListenerDriver: + def test_publish_event(self): + executor = MagicMock() + executor.__enter__.return_value = executor + driver = MockEventListenerDriver(futures_executor_fn=lambda: executor) + + driver.publish_event(MockEvent().to_dict()) + + executor.__enter__.assert_called_once() + executor.submit.assert_called_once() + executor.__exit__.assert_called_once() + def test__safe_try_publish_event(self): driver = MockEventListenerDriver(batched=False) From db9051d107d47d6df9756211d2f80dba7920d19c Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 1 Jul 2024 19:27:00 -0500 Subject: [PATCH 29/87] `typos` to dev dependencies to catch typos in code/docs. (#923) --- .github/workflows/code-checks.yml | 13 ++++++++++ .pre-commit-config.yaml | 7 ++++++ CHANGELOG.md | 1 + Makefile | 6 ++++- _typos.toml | 8 ++++++ .../drivers/prompt-drivers.md | 2 +- .../drivers/web-search-drivers.md | 2 +- docs/griptape-framework/misc/tokenizers.md | 2 +- docs/griptape-framework/structures/tasks.md | 2 +- .../file_manager/base_file_manager_driver.py | 2 +- griptape/drivers/prompt/base_prompt_driver.py | 2 +- poetry.lock | 25 ++++++++++++++++--- pyproject.toml | 1 + .../test_amazon_s3_file_manager_driver.py | 4 +-- .../test_local_file_manager_driver.py | 4 +-- .../test_redis_conversation_memory_driver.py | 2 +- .../vector/test_redis_vector_store_driver.py | 1 - tests/unit/structures/test_workflow.py | 2 +- 18 files changed, 68 insertions(+), 18 deletions(-) create mode 100644 _typos.toml diff --git a/.github/workflows/code-checks.yml b/.github/workflows/code-checks.yml index 03b1f0a17..51ffc543f 100644 --- a/.github/workflows/code-checks.yml +++ b/.github/workflows/code-checks.yml @@ -70,3 +70,16 @@ jobs: verbose: true env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + spell-check: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: [ "3.12" ] + steps: + - name: Checkout actions + uses: actions/checkout@v3 + - name: Init environment + uses: ./.github/actions/init-environment + - name: Run linter + run: make check/spell diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a54182464..33a90d824 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,3 +25,10 @@ repos: entry: make check/types language: system types: [python] +- repo: local + hooks: + - id: typos + name: Typos + entry: make check/spell + language: system + types: [python] diff --git a/CHANGELOG.md b/CHANGELOG.md index ddb48c4f5..273fe5429 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `VectorStoreClient.process_query_output_fn` for custom query output processing logic. - Parameter `fail_fast` to `Structure`. - `BooleanArtifact` for handling boolean values. +- `typos` to dev dependencies to catch typos in code/docs. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. diff --git a/Makefile b/Makefile index b4f3d0068..57d1869ce 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ format: ## Format project. @poetry run ruff format . .PHONY: check -check: check/format check/lint check/types ## Run all checks. +check: check/format check/lint check/types check/spell ## Run all checks. .PHONY: check/format check/format: @@ -53,6 +53,10 @@ check/lint: .PHONY: check/types check/types: @poetry run pyright griptape/ + +.PHONY: check/spell +check/spell: + @poetry run typos .DEFAULT_GOAL := help .PHONY: help diff --git a/_typos.toml b/_typos.toml new file mode 100644 index 000000000..1819b51ef --- /dev/null +++ b/_typos.toml @@ -0,0 +1,8 @@ +[default.extend-words] +# Don't correct the state ND +ND = "ND" +# Don't correct pirates using acronyms +mornin = "mornin" + +[files] +extend-exclude = ["docs/assets", "tests/resources/"] diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index 96a1be4e1..9d5b6fc4a 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -57,7 +57,7 @@ print(result.value) Griptape offers the following Prompt Drivers for interacting with LLMs. !!! warning - When overriding a default Prompt Driver, take care to ensure you've updated the Structure's configured Embedding Driver as well. If Task Memory isn't needed, you can avoid compatability issues by setting `task_memory=None` to disable Task Memory in your Structure. + When overriding a default Prompt Driver, take care to ensure you've updated the Structure's configured Embedding Driver as well. If Task Memory isn't needed, you can avoid compatibility issues by setting `task_memory=None` to disable Task Memory in your Structure. ### OpenAI Chat diff --git a/docs/griptape-framework/drivers/web-search-drivers.md b/docs/griptape-framework/drivers/web-search-drivers.md index 332ce2c2b..18ba1e21c 100644 --- a/docs/griptape-framework/drivers/web-search-drivers.md +++ b/docs/griptape-framework/drivers/web-search-drivers.md @@ -2,7 +2,7 @@ Web Search Drivers can be used to search for links from a search query. They are used by [WebSearch](../../reference/griptape/tools/web_search/tool.md) to provide its functionality. All Web Search Drivers implement the following methods: -* `search()` searchs the web and returns a [ListArtifact](../../reference/griptape/artifacts/list_artifact.md) that contains JSON-serializable [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s with the search results. +* `search()` searches the web and returns a [ListArtifact](../../reference/griptape/artifacts/list_artifact.md) that contains JSON-serializable [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s with the search results. ## Google diff --git a/docs/griptape-framework/misc/tokenizers.md b/docs/griptape-framework/misc/tokenizers.md index 1920e912e..a6df1c388 100644 --- a/docs/griptape-framework/misc/tokenizers.md +++ b/docs/griptape-framework/misc/tokenizers.md @@ -1,7 +1,7 @@ ## Overview Tokenizers are used throughout Griptape to calculate the number of [tokens](https://learn.microsoft.com/en-us/semantic-kernel/prompt-engineering/tokens) in a piece of text. -They are particulary useful for ensuring that the LLM token limits are not exceeded. +They are particularly useful for ensuring that the LLM token limits are not exceeded. Tokenizers are a low level abstraction that you will rarely interact with directly. diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index 6bb517fa2..e8f75b453 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -516,7 +516,7 @@ engine = VariationImageGenerationEngine( with open("tests/resources/mountain.png", "rb") as f: image_artifact = ImageLoader().load(f.read()) -# Instatiate a pipeline. +# Instantiate a pipeline. pipeline = Pipeline() # Add a VariationImageGenerationTask to the pipeline. diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index 56f19b3cc..562d8be4c 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -12,7 +12,7 @@ class BaseFileManagerDriver(ABC): Attributes: default_loader: The default loader to use for loading file contents into artifacts. - loaders: Dictionary of file extension specifc loaders to use for loading file contents into artifacts. + loaders: Dictionary of file extension specific loaders to use for loading file contents into artifacts. """ default_loader: loaders.BaseLoader = field(default=Factory(lambda: loaders.BlobLoader()), kw_only=True) diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 45f95d544..90e5259ac 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -16,7 +16,7 @@ @define(kw_only=True) class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): - """Base class for Prompt Drivers. + """Base class for the Prompt Drivers. Attributes: temperature: The temperature to use for the completion. diff --git a/poetry.lock b/poetry.lock index e030c8906..768a4e8ae 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohttp" @@ -3360,7 +3360,6 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ - {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4abe7fef64914ccfa909bc2ba39739670ecc9e820c83ccc7a6ed414122599b83"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1"}, ] @@ -4598,7 +4597,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -5979,6 +5977,25 @@ files = [ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, ] +[[package]] +name = "typos" +version = "1.22.9" +description = "Source Code Spelling Correction" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typos-1.22.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6221400b82554f853e1d1a0f26bcfddf9f36008114d3441c566e1b5edf20d27d"}, + {file = "typos-1.22.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a57b5f0acd1596034fdc333f94d4713adbc181c545fb526cf2119d2af4c007ec"}, + {file = "typos-1.22.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77e2d9dfee24cccf177b09d8ace6d6012fa8c453aa092d869426bfef3dd8c67e"}, + {file = "typos-1.22.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c38886031f4570d546b63ec112aed6b323762022ca5cc64d52537724a1529257"}, + {file = "typos-1.22.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8577b482256538822f76c9825d36f76b7b1e7cbccf2842279a7b46f0494796a5"}, + {file = "typos-1.22.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:63f7ae86eb7dccc43845bf0ef72a3746b1022889a178809c028f809081c6f20d"}, + {file = "typos-1.22.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5f290b85f1dddc875d4efa0b22802413f86532b99fa0ac2cb8d2e70eda68acfd"}, + {file = "typos-1.22.9-py3-none-win32.whl", hash = "sha256:76a58b1d54ee00ef8d90c3166b149e70d84b0414617a34abf5ded1db76feecef"}, + {file = "typos-1.22.9-py3-none-win_amd64.whl", hash = "sha256:53f31a9c0d321132f680ab92d80f7c520e163c53c9042fb009feaa91d9b4a7c4"}, + {file = "typos-1.22.9.tar.gz", hash = "sha256:c7b5feada41ce26e34eea1145141887257e59384d0ceea00f0f03349335ff688"}, +] + [[package]] name = "tzdata" version = "2024.1" @@ -6395,4 +6412,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "ce26764ee2c4a9a99d24ef4afc7efa6aa894a7560a725388ff24db15f6014e9a" +content-hash = "937d5e870407a493038178b3060c663feb9a1b6e6fc16e55fa380a18d02b0c80" diff --git a/pyproject.toml b/pyproject.toml index 29d4fda44..7fc62d6af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -174,6 +174,7 @@ ruff = "^0.4.6" pyright = "^1.1.363" pre-commit = "^3.7.1" boto3-stubs = {extras = ["bedrock", "iam", "opensearch", "s3", "sagemaker"], version = "^1.34.105"} +typos = "^1.22.9" [tool.poetry.group.docs] diff --git a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py index 285cf9510..8d1693ade 100644 --- a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py @@ -84,7 +84,7 @@ def test_validate_workdir(self, workdir, session, bucket): @pytest.mark.parametrize( "workdir,path,expected", [ - # Valid non-empty directories (witout trailing slash) + # Valid non-empty directories (without trailing slash) ("/", "", ["foo", "foo.txt", "foo-empty", "resources"]), ("/", "foo", ["bar", "bar.txt", "bar-empty"]), ("/", "foo/bar", ["baz.txt", "baz-empty"]), @@ -111,7 +111,7 @@ def test_validate_workdir(self, workdir, session, bucket): ("/./..", "bar/..", ["foo", "foo.txt", "foo-empty", "resources"]), ("/./..", "foo/.", ["bar", "bar.txt", "bar-empty"]), ("/./..", "foo/bar/.", ["baz.txt", "baz-empty"]), - # Empty folders (witout trailing slash) + # Empty folders (without trailing slash) ("/", "foo-empty", []), ("/", "foo/bar-empty", []), ("/", "foo/bar/baz-empty", []), diff --git a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py index 236281739..b3f4ec561 100644 --- a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py @@ -57,7 +57,7 @@ def test_validate_workdir(self): @pytest.mark.parametrize( "workdir,path,expected", [ - # Valid non-empty directories (witout trailing slash) + # Valid non-empty directories (without trailing slash) ("/", "", ["foo", "foo.txt", "foo-empty", "resources"]), ("/", "foo", ["bar", "bar.txt", "bar-empty"]), ("/", "foo/bar", ["baz.txt", "baz-empty"]), @@ -84,7 +84,7 @@ def test_validate_workdir(self): ("/./..", "bar/..", ["foo", "foo.txt", "foo-empty", "resources"]), ("/./..", "foo/.", ["bar", "bar.txt", "bar-empty"]), ("/./..", "foo/bar/.", ["baz.txt", "baz-empty"]), - # Empty folders (witout trailing slash) + # Empty folders (without trailing slash) ("/", "foo-empty", []), ("/", "foo/bar-empty", []), ("/", "foo/bar/baz-empty", []), diff --git a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py index dee840508..13f75d464 100644 --- a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py @@ -5,7 +5,7 @@ TEST_CONVERSATION = '{"type": "ConversationMemory", "runs": [{"type": "Run", "id": "729ca6be5d79433d9762eb06dfd677e2", "input": "Hi There, Hello", "output": "Hello! How can I assist you today?"}], "max_runs": 2}' CONVERSATION_ID = "117151897f344ff684b553d0655d8f39" -INDEX = "griptape_converstaion" +INDEX = "griptape_conversation" HOST = "127.0.0.1" PORT = 6379 PASSWORD = "" diff --git a/tests/unit/drivers/vector/test_redis_vector_store_driver.py b/tests/unit/drivers/vector/test_redis_vector_store_driver.py index 3c98180e7..18759a2d7 100644 --- a/tests/unit/drivers/vector/test_redis_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_redis_vector_store_driver.py @@ -1,6 +1,5 @@ from unittest.mock import MagicMock import pytest -import redis from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from griptape.drivers import RedisVectorStoreDriver diff --git a/tests/unit/structures/test_workflow.py b/tests/unit/structures/test_workflow.py index 2b89684d3..bf55e852f 100644 --- a/tests/unit/structures/test_workflow.py +++ b/tests/unit/structures/test_workflow.py @@ -683,7 +683,7 @@ def test_output_task(self): # task4 is the final task, but its defined at index 0 workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[task4, task1, task2, task3]) - # ouput_task topologically should be task4 + # output_task topologically should be task4 assert task4 == workflow.output_task def test_to_graph(self): From 2dcfe2d55c06fcf0c53ae259aae8c393019d46ef Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 2 Jul 2024 09:48:39 -0500 Subject: [PATCH 30/87] Refactor prompt stack (#861) --- CHANGELOG.md | 26 ++++ README.md | 2 +- .../drivers/prompt-drivers.md | 24 ++-- docs/griptape-framework/misc/events.md | 8 +- docs/griptape-framework/structures/agents.md | 2 +- docs/griptape-framework/structures/tasks.md | 27 +++- griptape/common/__init__.py | 23 +++ griptape/common/prompt_stack/__init__.py | 0 .../common/prompt_stack/contents/__init__.py | 0 .../contents/base_delta_message_content.py | 12 ++ .../contents/base_message_content.py | 31 ++++ .../contents/image_message_content.py | 17 +++ .../contents/text_delta_message_content.py | 9 ++ .../contents/text_message_content.py | 20 +++ .../common/prompt_stack/messages/__init__.py | 0 .../prompt_stack/messages/base_message.py | 44 ++++++ .../prompt_stack/messages/delta_message.py | 15 ++ .../common/prompt_stack/messages/message.py | 38 +++++ griptape/common/prompt_stack/prompt_stack.py | 56 ++++++++ griptape/config/google_structure_config.py | 4 +- .../prompt/amazon_bedrock_prompt_driver.py | 78 ++++++++--- ...mazon_sagemaker_jumpstart_prompt_driver.py | 61 +++++--- .../drivers/prompt/anthropic_prompt_driver.py | 118 +++++++++++----- .../prompt/azure_openai_chat_prompt_driver.py | 2 +- griptape/drivers/prompt/base_prompt_driver.py | 101 +++++++++----- .../drivers/prompt/cohere_prompt_driver.py | 81 ++++++++--- .../drivers/prompt/dummy_prompt_driver.py | 17 ++- .../drivers/prompt/google_prompt_driver.py | 108 ++++++++++---- .../prompt/huggingface_hub_prompt_driver.py | 43 ++++-- .../huggingface_pipeline_prompt_driver.py | 44 +++--- .../drivers/prompt/ollama_prompt_driver.py | 38 ++++- .../prompt/openai_chat_prompt_driver.py | 132 +++++++++++++----- .../extraction/csv_extraction_engine.py | 11 +- .../extraction/json_extraction_engine.py | 11 +- .../engines/rag/modules/base_rag_module.py | 7 +- .../prompt_generation_rag_module.py | 8 +- .../engines/summary/prompt_summary_engine.py | 24 ++-- griptape/events/base_prompt_event.py | 1 - griptape/events/finish_prompt_event.py | 3 + griptape/events/start_prompt_event.py | 3 +- .../structure/base_conversation_memory.py | 18 +-- .../memory/structure/conversation_memory.py | 6 +- griptape/memory/structure/run.py | 5 +- .../structure/summary_conversation_memory.py | 12 +- griptape/schemas/base_schema.py | 4 +- griptape/structures/agent.py | 21 ++- griptape/structures/pipeline.py | 7 +- griptape/structures/workflow.py | 7 +- griptape/tasks/prompt_task.py | 69 +++++++-- griptape/tasks/toolkit_task.py | 12 +- .../tokenizers/amazon_bedrock_tokenizer.py | 1 + griptape/tokenizers/huggingface_tokenizer.py | 1 + griptape/tokenizers/openai_tokenizer.py | 7 +- griptape/tokenizers/voyageai_tokenizer.py | 7 +- .../prompt_image_generation_client/tool.py | 9 +- griptape/utils/__init__.py | 2 - griptape/utils/conversation.py | 4 +- griptape/utils/prompt_stack.py | 48 ------- tests/mocks/mock_failing_prompt_driver.py | 26 ++-- tests/mocks/mock_prompt_driver.py | 28 ++-- tests/mocks/mock_value_prompt_driver.py | 21 --- .../config/test_google_structure_config.py | 2 +- ...est_dynamodb_conversation_memory_driver.py | 4 +- .../test_local_conversation_memory_driver.py | 8 +- .../test_redis_conversation_memory_driver.py | 2 +- .../test_amazon_bedrock_prompt_driver.py | 61 ++++---- ...mazon_sagemaker_jumpstart_prompt_driver.py | 14 +- .../prompt/test_anthropic_prompt_driver.py | 98 +++++++++---- .../test_azure_openai_chat_prompt_driver.py | 40 +++--- .../drivers/prompt/test_base_prompt_driver.py | 11 +- .../prompt/test_cohere_prompt_driver.py | 105 +++++++------- .../prompt/test_google_prompt_driver.py | 106 +++++++------- .../test_hugging_face_hub_prompt_driver.py | 27 ++-- ...est_hugging_face_pipeline_prompt_driver.py | 16 ++- .../prompt/test_ollama_prompt_driver.py | 41 ++++-- .../prompt/test_openai_chat_prompt_driver.py | 107 +++++++------- .../summary/test_prompt_summary_engine.py | 4 +- tests/unit/events/test_base_event.py | 43 ++++-- tests/unit/events/test_finish_prompt_event.py | 5 +- tests/unit/events/test_start_prompt_event.py | 18 ++- .../structure/test_conversation_memory.py | 113 +++++++-------- .../test_summary_conversation_memory.py | 28 ++-- tests/unit/structures/test_agent.py | 12 +- tests/unit/structures/test_pipeline.py | 24 ++-- tests/unit/tasks/test_prompt_task.py | 86 ++++++++++++ tests/unit/tasks/test_toolkit_task.py | 8 +- .../unit/tokenizers/test_google_tokenizer.py | 5 +- tests/unit/utils/test_base_tokenizer.py | 13 ++ tests/unit/utils/test_message_stack.py | 55 ++++++++ tests/unit/utils/test_prompt_stack.py | 41 ------ 90 files changed, 1787 insertions(+), 874 deletions(-) create mode 100644 griptape/common/__init__.py create mode 100644 griptape/common/prompt_stack/__init__.py create mode 100644 griptape/common/prompt_stack/contents/__init__.py create mode 100644 griptape/common/prompt_stack/contents/base_delta_message_content.py create mode 100644 griptape/common/prompt_stack/contents/base_message_content.py create mode 100644 griptape/common/prompt_stack/contents/image_message_content.py create mode 100644 griptape/common/prompt_stack/contents/text_delta_message_content.py create mode 100644 griptape/common/prompt_stack/contents/text_message_content.py create mode 100644 griptape/common/prompt_stack/messages/__init__.py create mode 100644 griptape/common/prompt_stack/messages/base_message.py create mode 100644 griptape/common/prompt_stack/messages/delta_message.py create mode 100644 griptape/common/prompt_stack/messages/message.py create mode 100644 griptape/common/prompt_stack/prompt_stack.py delete mode 100644 griptape/utils/prompt_stack.py delete mode 100644 tests/mocks/mock_value_prompt_driver.py create mode 100644 tests/unit/utils/test_base_tokenizer.py create mode 100644 tests/unit/utils/test_message_stack.py delete mode 100644 tests/unit/utils/test_prompt_stack.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 273fe5429..1d270363c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,32 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +### Added +- `Message` for storing messages in a `PromptStack`. Messages consist of a role, content, and usage. +- `DeltaMessage` for storing partial messages in a `PromptStack`. Multiple `DeltaMessage` can be combined to form a `Message`. +- `TextMessageContent` for storing textual content in a `Message`. +- `ImageMessageContent` for storing image content in a `Message`. +- Support for adding `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s to `PromptStack`. +- Support for image inputs to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AmazonBedrockPromptDriver`, `AnthropicPromptDriver`, and `GooglePromptDriver`. +- Input/output token usage metrics to all Prompt Drivers. +- `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. +- Support for storing Artifacts as inputs/outputs in Conversation Memory Runs. +- `Agent.input` for passing Artifacts as input. +- Support for `PromptTask`s to take `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s as input. + +### Changed +- **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. +- **BREAKING**: Renamed `PromptStack.inputs` to `PromptStack.messages`. +- **BREAKING**: Moved `PromptStack.USER_ROLE`, `PromptStack.ASSISTANT_ROLE`, and `PromptStack.SYSTEM_ROLE` to `Message`. +- **BREAKING**: Updated return type of `PromptDriver.try_run` from `TextArtifact` to `Message`. +- **BREAKING**: Updated return type of `PromptDriver.try_stream` from `Iterator[TextArtifact]` to `Iterator[DeltaMessage]`. +- **BREAKING**: Removed `BasePromptEvent.token_count` in favor of `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. +- **BREAKING**: Removed `StartPromptEvent.prompt`. Use `StartPromptEvent.prompt_stack` instead. +- **BREAKING**: Removed `Agent.input_template` in favor of `Agent.input`. +- **BREAKING**: `BasePromptDriver.run` now returns a `Message` instead of a `TextArtifact`. For compatibility, `Message.value` contains the Message's Artifact value +- Default Prompt Driver model in `GoogleStructureConfig` to `gemini-1.5-pro`. + + ### Added - `RagEngine` is an abstraction for implementing modular RAG pipelines. diff --git a/README.md b/README.md index f9eb2aa5c..6905903a3 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ from griptape.structures import Agent from griptape.tools import WebScraper, FileManager, TaskMemoryClient agent = Agent( - input_template="Load {{ args[0] }}, summarize it, and store it in a file called {{ args[1] }}.", + input="Load {{ args[0] }}, summarize it, and store it in a file called {{ args[1] }}.", tools=[ WebScraper(off_prompt=True), TaskMemoryClient(off_prompt=True), diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index 9d5b6fc4a..f95a0ba4e 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -14,7 +14,7 @@ agent = Agent( config=StructureConfig( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o", temperature=0.3), ), - input_template="You will be provided with a tweet, and your task is to classify its sentiment as positive, neutral, or negative. Tweet: {{ args[0] }}", + input="You will be provided with a tweet, and your task is to classify its sentiment as positive, neutral, or negative. Tweet: {{ args[0] }}", rules=[ Rule( value="Output only the sentiment." @@ -28,23 +28,23 @@ agent.run("I loved the new Batman movie!") Or use them independently: ```python -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.drivers import OpenAiChatPromptDriver stack = PromptStack() -stack.add_system_input( +stack.add_system_message( "You will be provided with Python code, and your task is to calculate its time complexity." ) stack.add_user_input( -""" -def foo(n, k): - accum = 0 - for i in range(n): - for l in range(k): - accum += i - return accum -""" + """ + def foo(n, k): + accum = 0 + for i in range(n): + for l in range(k): + accum += i + return accum + """ ) result = OpenAiChatPromptDriver(model="gpt-3.5-turbo-16k", temperature=0).run(stack) @@ -80,7 +80,7 @@ agent = Agent( seed=42, ) ), - input_template="You will be provided with a description of a mood, and your task is to generate the CSS code for a color that matches it. Description: {{ args[0] }}", + input="You will be provided with a description of a mood, and your task is to generate the CSS code for a color that matches it. Description: {{ args[0] }}", rules=[ Rule( value='Write your output in json with a single key called "css_code".' diff --git a/docs/griptape-framework/misc/events.md b/docs/griptape-framework/misc/events.md index 0921676fb..2d3645e94 100644 --- a/docs/griptape-framework/misc/events.md +++ b/docs/griptape-framework/misc/events.md @@ -244,9 +244,9 @@ from griptape.events import BaseEvent, StartPromptEvent, EventListener def handler(event: BaseEvent): if isinstance(event, StartPromptEvent): - print("Prompt Stack Inputs:") - for input in event.prompt_stack.inputs: - print(f"{input.role}: {input.content}") + print("Prompt Stack PromptStack:") + for message in event.prompt_stack.messages: + print(f"{message.role}: {message.content}") print("Final Prompt String:") print(event.prompt) @@ -259,7 +259,7 @@ agent.run("Write me a poem.") ``` ``` ... -Prompt Stack Inputs: +Prompt Stack Messages: system: user: Write me a poem. Final Prompt String: diff --git a/docs/griptape-framework/structures/agents.md b/docs/griptape-framework/structures/agents.md index 8737d2a59..b36db72d3 100644 --- a/docs/griptape-framework/structures/agents.md +++ b/docs/griptape-framework/structures/agents.md @@ -15,7 +15,7 @@ from griptape.structures import Agent agent = Agent( - input_template="Calculate the following: {{ args[0] }}", + input="Calculate the following: {{ args[0] }}", tools=[Calculator()] ) diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index e8f75b453..c385df6cd 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -88,6 +88,31 @@ agent.run("Write me a haiku") Day begins anew. ``` +If the model supports it, you can also pass image inputs: + +```python +from griptape.structures import Agent +from griptape.loaders import ImageLoader + +agent = Agent() +with open("tests/resources/mountain.jpg", "rb") as f: + image_artifact = ImageLoader().load(f.read()) + +agent.run(["What's in this image?", image_artifact]) +``` + +``` +[06/21/24 10:01:08] INFO PromptTask c229d1792da34ab1a7c45768270aada9 + Input: What's in this image? + + Media, type: image/jpeg, size: 82351 bytes +[06/21/24 10:01:12] INFO PromptTask c229d1792da34ab1a7c45768270aada9 + Output: The image depicts a stunning mountain landscape at sunrise or sunset. The sun is partially visible on the left side of the image, + casting a warm golden light over the scene. The mountains are covered with snow at their peaks, and a layer of clouds or fog is settled in the + valleys between them. The sky is a mix of warm colors near the horizon, transitioning to cooler blues higher up, with some scattered clouds + adding texture to the sky. The overall scene is serene and majestic, highlighting the natural beauty of the mountainous terrain. +``` + ## Toolkit Task To use [Griptape Tools](../../griptape-framework/tools/index.md), use a [Toolkit Task](../../reference/griptape/tasks/toolkit_task.md). @@ -740,7 +765,7 @@ def build_researcher(): def build_writer(): writer = Agent( - input_template="Instructions: {{args[0]}}\nContext: {{args[1]}}", + input="Instructions: {{args[0]}}\nContext: {{args[1]}}", rulesets=[ Ruleset( name="Position", diff --git a/griptape/common/__init__.py b/griptape/common/__init__.py new file mode 100644 index 000000000..2b1189472 --- /dev/null +++ b/griptape/common/__init__.py @@ -0,0 +1,23 @@ +from .prompt_stack.contents.base_message_content import BaseMessageContent +from .prompt_stack.contents.base_delta_message_content import BaseDeltaMessageContent +from .prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent +from .prompt_stack.contents.text_message_content import TextMessageContent +from .prompt_stack.contents.image_message_content import ImageMessageContent + +from .prompt_stack.messages.base_message import BaseMessage +from .prompt_stack.messages.delta_message import DeltaMessage +from .prompt_stack.messages.message import Message + +from .prompt_stack.prompt_stack import PromptStack + +__all__ = [ + "BaseMessage", + "BaseDeltaMessageContent", + "BaseMessageContent", + "DeltaMessage", + "Message", + "TextDeltaMessageContent", + "TextMessageContent", + "ImageMessageContent", + "PromptStack", +] diff --git a/griptape/common/prompt_stack/__init__.py b/griptape/common/prompt_stack/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/common/prompt_stack/contents/__init__.py b/griptape/common/prompt_stack/contents/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/common/prompt_stack/contents/base_delta_message_content.py b/griptape/common/prompt_stack/contents/base_delta_message_content.py new file mode 100644 index 000000000..344f0bb7a --- /dev/null +++ b/griptape/common/prompt_stack/contents/base_delta_message_content.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from abc import ABC + +from attrs import define, field + +from griptape.mixins.serializable_mixin import SerializableMixin + + +@define +class BaseDeltaMessageContent(ABC, SerializableMixin): + index: int = field(kw_only=True, default=0, metadata={"serializable": True}) diff --git a/griptape/common/prompt_stack/contents/base_message_content.py b/griptape/common/prompt_stack/contents/base_message_content.py new file mode 100644 index 000000000..cd4d5bd92 --- /dev/null +++ b/griptape/common/prompt_stack/contents/base_message_content.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from abc import ABC +from collections.abc import Sequence + +from attrs import define, field + +from griptape.artifacts.base_artifact import BaseArtifact +from griptape.mixins import SerializableMixin + +from .base_delta_message_content import BaseDeltaMessageContent + + +@define +class BaseMessageContent(ABC, SerializableMixin): + artifact: BaseArtifact = field(metadata={"serializable": True}) + + def to_text(self) -> str: + return str(self.artifact) + + def __str__(self) -> str: + return self.artifact.to_text() + + def __bool__(self) -> bool: + return bool(self.artifact) + + def __len__(self) -> int: + return len(self.artifact) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> BaseMessageContent: ... diff --git a/griptape/common/prompt_stack/contents/image_message_content.py b/griptape/common/prompt_stack/contents/image_message_content.py new file mode 100644 index 000000000..0192a2cb4 --- /dev/null +++ b/griptape/common/prompt_stack/contents/image_message_content.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from collections.abc import Sequence + +from attrs import define, field + +from griptape.artifacts import ImageArtifact +from griptape.common import BaseDeltaMessageContent, BaseMessageContent + + +@define +class ImageMessageContent(BaseMessageContent): + artifact: ImageArtifact = field(metadata={"serializable": True}) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> ImageMessageContent: + raise NotImplementedError() diff --git a/griptape/common/prompt_stack/contents/text_delta_message_content.py b/griptape/common/prompt_stack/contents/text_delta_message_content.py new file mode 100644 index 000000000..ab5313df6 --- /dev/null +++ b/griptape/common/prompt_stack/contents/text_delta_message_content.py @@ -0,0 +1,9 @@ +from __future__ import annotations +from attrs import define, field + +from griptape.common import BaseDeltaMessageContent + + +@define +class TextDeltaMessageContent(BaseDeltaMessageContent): + text: str = field(metadata={"serializable": True}) diff --git a/griptape/common/prompt_stack/contents/text_message_content.py b/griptape/common/prompt_stack/contents/text_message_content.py new file mode 100644 index 000000000..1d7b2bd5b --- /dev/null +++ b/griptape/common/prompt_stack/contents/text_message_content.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +from attrs import define, field +from collections.abc import Sequence + +from griptape.artifacts import TextArtifact +from griptape.common import BaseMessageContent, BaseDeltaMessageContent, TextDeltaMessageContent + + +@define +class TextMessageContent(BaseMessageContent): + artifact: TextArtifact = field(metadata={"serializable": True}) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> TextMessageContent: + text_deltas = [delta for delta in deltas if isinstance(delta, TextDeltaMessageContent)] + + artifact = TextArtifact(value="".join(delta.text for delta in text_deltas)) + + return cls(artifact=artifact) diff --git a/griptape/common/prompt_stack/messages/__init__.py b/griptape/common/prompt_stack/messages/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/common/prompt_stack/messages/base_message.py b/griptape/common/prompt_stack/messages/base_message.py new file mode 100644 index 000000000..3cc8e532a --- /dev/null +++ b/griptape/common/prompt_stack/messages/base_message.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +from abc import ABC +from typing import Optional, Union +from attrs import Factory, define, field + + +from griptape.common import BaseMessageContent, BaseDeltaMessageContent +from griptape.mixins import SerializableMixin + + +@define +class BaseMessage(ABC, SerializableMixin): + @define + class Usage(SerializableMixin): + input_tokens: Optional[float] = field(kw_only=True, default=None, metadata={"serializable": True}) + output_tokens: Optional[float] = field(kw_only=True, default=None, metadata={"serializable": True}) + + @property + def total_tokens(self) -> float: + return (self.input_tokens or 0) + (self.output_tokens or 0) + + def __add__(self, other: BaseMessage.Usage) -> BaseMessage.Usage: + return BaseMessage.Usage( + input_tokens=(self.input_tokens or 0) + (other.input_tokens or 0), + output_tokens=(self.output_tokens or 0) + (other.output_tokens or 0), + ) + + USER_ROLE = "user" + ASSISTANT_ROLE = "assistant" + SYSTEM_ROLE = "system" + + content: list[Union[BaseMessageContent, BaseDeltaMessageContent]] = field(metadata={"serializable": True}) + role: str = field(kw_only=True, metadata={"serializable": True}) + usage: Usage = field(kw_only=True, default=Factory(lambda: BaseMessage.Usage()), metadata={"serializable": True}) + + def is_system(self) -> bool: + return self.role == self.SYSTEM_ROLE + + def is_user(self) -> bool: + return self.role == self.USER_ROLE + + def is_assistant(self) -> bool: + return self.role == self.ASSISTANT_ROLE diff --git a/griptape/common/prompt_stack/messages/delta_message.py b/griptape/common/prompt_stack/messages/delta_message.py new file mode 100644 index 000000000..7ff90b08f --- /dev/null +++ b/griptape/common/prompt_stack/messages/delta_message.py @@ -0,0 +1,15 @@ +from __future__ import annotations +from typing import Optional + +from attrs import define, field + +from griptape.common.prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent + + +from .base_message import BaseMessage + + +@define +class DeltaMessage(BaseMessage): + role: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) + content: Optional[TextDeltaMessageContent] = field(kw_only=True, default=None, metadata={"serializable": True}) diff --git a/griptape/common/prompt_stack/messages/message.py b/griptape/common/prompt_stack/messages/message.py new file mode 100644 index 000000000..fcf6750ea --- /dev/null +++ b/griptape/common/prompt_stack/messages/message.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact +from griptape.common import BaseMessageContent, TextMessageContent + +from .base_message import BaseMessage + + +@define +class Message(BaseMessage): + def __init__(self, content: str | list[BaseMessageContent], **kwargs: Any): + if isinstance(content, str): + content = [TextMessageContent(TextArtifact(value=content))] + self.__attrs_init__(content, **kwargs) # pyright: ignore[reportAttributeAccessIssue] + + content: list[BaseMessageContent] = field(metadata={"serializable": True}) + + @property + def value(self) -> Any: + return self.to_artifact().value + + def __str__(self) -> str: + return self.to_text() + + def to_text(self) -> str: + return "".join( + [content.artifact.to_text() for content in self.content if isinstance(content, TextMessageContent)] + ) + + def to_artifact(self) -> BaseArtifact: + if len(self.content) == 1: + return self.content[0].artifact + else: + return ListArtifact([content.artifact for content in self.content]) diff --git a/griptape/common/prompt_stack/prompt_stack.py b/griptape/common/prompt_stack/prompt_stack.py new file mode 100644 index 000000000..ce19696e3 --- /dev/null +++ b/griptape/common/prompt_stack/prompt_stack.py @@ -0,0 +1,56 @@ +from __future__ import annotations +from attrs import define, field + +from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact, ImageArtifact +from griptape.mixins import SerializableMixin +from griptape.common import Message, TextMessageContent, BaseMessageContent, ImageMessageContent + + +@define +class PromptStack(SerializableMixin): + messages: list[Message] = field(factory=list, kw_only=True, metadata={"serializable": True}) + + @property + def system_messages(self) -> list[Message]: + return [message for message in self.messages if message.is_system()] + + @property + def user_messages(self) -> list[Message]: + return [message for message in self.messages if message.is_user()] + + @property + def assistant_messages(self) -> list[Message]: + return [message for message in self.messages if message.is_assistant()] + + def add_message(self, artifact: str | BaseArtifact, role: str) -> Message: + new_content = self.__process_artifact(artifact) + + self.messages.append(Message(content=new_content, role=role)) + + return self.messages[-1] + + def add_system_message(self, artifact: str | BaseArtifact) -> Message: + return self.add_message(artifact, Message.SYSTEM_ROLE) + + def add_user_message(self, artifact: str | BaseArtifact) -> Message: + return self.add_message(artifact, Message.USER_ROLE) + + def add_assistant_message(self, artifact: str | BaseArtifact) -> Message: + return self.add_message(artifact, Message.ASSISTANT_ROLE) + + def __process_artifact(self, artifact: str | BaseArtifact) -> list[BaseMessageContent]: + if isinstance(artifact, str): + return [TextMessageContent(TextArtifact(artifact))] + elif isinstance(artifact, TextArtifact): + return [TextMessageContent(artifact)] + elif isinstance(artifact, ImageArtifact): + return [ImageMessageContent(artifact)] + elif isinstance(artifact, ListArtifact): + processed_contents = [self.__process_artifact(artifact) for artifact in artifact.value] + flattened_content = [ + sub_content for processed_content in processed_contents for sub_content in processed_content + ] + + return flattened_content + else: + raise ValueError(f"Unsupported artifact type: {type(artifact)}") diff --git a/griptape/config/google_structure_config.py b/griptape/config/google_structure_config.py index 744d08782..fc0548ff7 100644 --- a/griptape/config/google_structure_config.py +++ b/griptape/config/google_structure_config.py @@ -14,7 +14,9 @@ @define class GoogleStructureConfig(StructureConfig): prompt_driver: BasePromptDriver = field( - default=Factory(lambda: GooglePromptDriver(model="gemini-pro")), kw_only=True, metadata={"serializable": True} + default=Factory(lambda: GooglePromptDriver(model="gemini-1.5-pro")), + kw_only=True, + metadata={"serializable": True}, ) embedding_driver: BaseEmbeddingDriver = field( default=Factory(lambda: GoogleEmbeddingDriver(model="models/embedding-001")), diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 849ed0901..21d81724d 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -6,6 +6,14 @@ from attrs import Factory, define, field from griptape.artifacts import TextArtifact +from griptape.common import ( + DeltaMessage, + Message, + TextDeltaMessageContent, + BaseMessageContent, + TextMessageContent, + ImageMessageContent, +) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AmazonBedrockTokenizer, BaseTokenizer from griptape.utils import import_optional_dependency @@ -13,7 +21,7 @@ if TYPE_CHECKING: import boto3 - from griptape.utils import PromptStack + from griptape.common import PromptStack @define @@ -27,44 +35,54 @@ class AmazonBedrockPromptDriver(BasePromptDriver): default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: response = self.bedrock_client.converse(**self._base_params(prompt_stack)) + usage = response["usage"] output_message = response["output"]["message"] - output_content = output_message["content"][0]["text"] - return TextArtifact(output_content) + return Message( + content=[TextMessageContent(TextArtifact(content["text"])) for content in output_message["content"]], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=usage["inputTokens"], output_tokens=usage["outputTokens"]), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: response = self.bedrock_client.converse_stream(**self._base_params(prompt_stack)) stream = response.get("stream") if stream is not None: for event in stream: if "contentBlockDelta" in event: - yield TextArtifact(event["contentBlockDelta"]["delta"]["text"]) + content_block_delta = event["contentBlockDelta"] + yield DeltaMessage( + content=TextDeltaMessageContent( + content_block_delta["delta"]["text"], index=content_block_delta["contentBlockIndex"] + ) + ) + elif "metadata" in event: + usage = event["metadata"]["usage"] + yield DeltaMessage( + usage=DeltaMessage.Usage(input_tokens=usage["inputTokens"], output_tokens=usage["outputTokens"]) + ) else: raise Exception("model response is empty") - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - content = [{"text": prompt_input.content}] - - if prompt_input.is_system(): - return {"text": prompt_input.content} - elif prompt_input.is_assistant(): - return {"role": "assistant", "content": content} - else: - return {"role": "user", "content": content} + def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: + return [ + { + "role": self.__to_role(message), + "content": [self.__prompt_stack_content_message_content(content) for content in message.content], + } + for message in messages + ] def _base_params(self, prompt_stack: PromptStack) -> dict: - system_messages = [ - self._prompt_stack_input_to_message(input) - for input in prompt_stack.inputs - if input.is_system() and input.content - ] - messages = [ - self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs if not input.is_system() - ] + system_messages = [{"text": message.to_text()} for message in prompt_stack.system_messages] + + messages = self._prompt_stack_messages_to_messages( + [message for message in prompt_stack.messages if not message.is_system()] + ) return { "modelId": self.model, @@ -73,3 +91,17 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "inferenceConfig": {"temperature": self.temperature}, "additionalModelRequestFields": self.additional_model_request_fields, } + + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"text": content.artifact.to_text()} + elif isinstance(content, ImageMessageContent): + return {"image": {"format": content.artifact.format, "source": {"bytes": content.artifact.value}}} + else: + raise ValueError(f"Unsupported content type: {type(content)}") + + def __to_role(self, message: Message) -> str: + if message.is_assistant(): + return "assistant" + else: + return "user" diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 18f8e4b77..dacaa62b0 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -7,14 +7,15 @@ from attrs import Factory, define, field from griptape.artifacts import TextArtifact -from griptape.drivers.prompt.base_prompt_driver import BasePromptDriver +from griptape.common import PromptStack, Message, TextMessageContent, DeltaMessage +from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: import boto3 - from griptape.utils import PromptStack + from griptape.common import PromptStack @define @@ -40,8 +41,11 @@ def validate_stream(self, _, stream): if stream: raise ValueError("streaming is not supported") - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - payload = {"inputs": self._to_model_input(prompt_stack), "parameters": self._to_model_params(prompt_stack)} + def try_run(self, prompt_stack: PromptStack) -> Message: + payload = { + "inputs": self.prompt_stack_to_string(prompt_stack), + "parameters": {**self._base_params(prompt_stack)}, + } response = self.sagemaker_client.invoke_endpoint( EndpointName=self.endpoint, @@ -59,31 +63,28 @@ def try_run(self, prompt_stack: PromptStack) -> TextArtifact: if isinstance(decoded_body, list): if decoded_body: - return TextArtifact(decoded_body[0]["generated_text"]) + generated_text = decoded_body[0]["generated_text"] else: raise ValueError("model response is empty") else: - return TextArtifact(decoded_body["generated_text"]) - - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - raise NotImplementedError("streaming is not supported") + generated_text = decoded_body["generated_text"] - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - return {"role": prompt_input.role, "content": prompt_input.content} + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + output_tokens = len(self.tokenizer.tokenizer.encode(generated_text)) - def _to_model_input(self, prompt_stack: PromptStack) -> str: - prompt = self.tokenizer.tokenizer.apply_chat_template( - [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], - tokenize=False, - add_generation_prompt=True, + return Message( + content=[TextMessageContent(TextArtifact(generated_text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), ) - if isinstance(prompt, str): - return prompt - else: - raise ValueError("Invalid output type.") + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: + raise NotImplementedError("streaming is not supported") - def _to_model_params(self, prompt_stack: PromptStack) -> dict: + def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: + return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) + + def _base_params(self, prompt_stack: PromptStack) -> dict: return { "temperature": self.temperature, "max_new_tokens": self.max_tokens, @@ -92,3 +93,21 @@ def _to_model_params(self, prompt_stack: PromptStack) -> dict: "stop_strings": self.tokenizer.stop_sequences, "return_full_text": False, } + + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + messages = [] + + for message in prompt_stack.messages: + messages.append({"role": message.role, "content": message.to_text()}) + + return messages + + def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: + messages = self._prompt_stack_to_messages(prompt_stack) + + tokens = self.tokenizer.tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=True) + + if isinstance(tokens, list): + return tokens + else: + raise ValueError("Invalid output type.") diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index b74a9d5f6..1dd7bb7f9 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -1,11 +1,27 @@ from __future__ import annotations -from typing import Optional, Any + from collections.abc import Iterator -from attrs import define, field, Factory +from typing import Any, Optional, TYPE_CHECKING + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack, import_optional_dependency +from griptape.common import ( + BaseMessageContent, + DeltaMessage, + TextDeltaMessageContent, + ImageMessageContent, + PromptStack, + Message, + TextMessageContent, +) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AnthropicTokenizer, BaseTokenizer +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from anthropic.types import ContentBlockDeltaEvent + from anthropic.types import ContentBlock @define @@ -32,42 +48,40 @@ class AnthropicPromptDriver(BasePromptDriver): top_k: int = field(default=250, kw_only=True, metadata={"serializable": True}) max_tokens: int = field(default=1000, kw_only=True, metadata={"serializable": True}) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: response = self.client.messages.create(**self._base_params(prompt_stack)) - return TextArtifact(value=response.content[0].text) + return Message( + content=[self.__message_content_to_prompt_stack_content(content) for content in response.content], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=response.usage.input_tokens, output_tokens=response.usage.output_tokens), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - response = self.client.messages.create(**self._base_params(prompt_stack), stream=True) + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: + events = self.client.messages.create(**self._base_params(prompt_stack), stream=True) - for chunk in response: - if chunk.type == "content_block_delta": - yield TextArtifact(value=chunk.delta.text) + for event in events: + if event.type == "content_block_delta": + yield DeltaMessage(content=self.__message_content_delta_to_prompt_stack_content_delta(event)) + elif event.type == "message_start": + yield DeltaMessage(usage=DeltaMessage.Usage(input_tokens=event.message.usage.input_tokens)) + elif event.type == "message_delta": + yield DeltaMessage(usage=DeltaMessage.Usage(output_tokens=event.usage.output_tokens)) - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - content = prompt_input.content + def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: + return [{"role": self.__to_role(message), "content": self.__to_content(message)} for message in messages] - if prompt_input.is_system(): - return {"role": "system", "content": content} - elif prompt_input.is_assistant(): - return {"role": "assistant", "content": content} - else: - return {"role": "user", "content": content} - - def _prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> dict: - messages = [ - self._prompt_stack_input_to_message(prompt_input) - for prompt_input in prompt_stack.inputs - if not prompt_input.is_system() - ] - system = next((self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs if i.is_system()), None) - - if system is None: - return {"messages": messages} + def _base_params(self, prompt_stack: PromptStack) -> dict: + messages = self._prompt_stack_messages_to_messages( + [message for message in prompt_stack.messages if not message.is_system()] + ) + + system_messages = prompt_stack.system_messages + if system_messages: + system_message = system_messages[0].to_text() else: - return {"messages": messages, "system": system["content"]} + system_message = None - def _base_params(self, prompt_stack: PromptStack) -> dict: return { "model": self.model, "temperature": self.temperature, @@ -75,5 +89,45 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "top_p": self.top_p, "top_k": self.top_k, "max_tokens": self.max_tokens, - **self._prompt_stack_to_model_input(prompt_stack), + "messages": messages, + **({"system": system_message} if system_message else {}), } + + def __to_role(self, message: Message) -> str: + if message.is_assistant(): + return "assistant" + else: + return "user" + + def __to_content(self, message: Message) -> str | list[dict]: + if all(isinstance(content, TextMessageContent) for content in message.content): + return message.to_text() + else: + return [self.__prompt_stack_content_message_content(content) for content in message.content] + + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"type": "text", "text": content.artifact.to_text()} + elif isinstance(content, ImageMessageContent): + return { + "type": "image", + "source": {"type": "base64", "media_type": content.artifact.mime_type, "data": content.artifact.base64}, + } + else: + raise ValueError(f"Unsupported prompt content type: {type(content)}") + + def __message_content_to_prompt_stack_content(self, content: ContentBlock) -> BaseMessageContent: + if content.type == "text": + return TextMessageContent(TextArtifact(content.text)) + else: + raise ValueError(f"Unsupported message content type: {content.type}") + + def __message_content_delta_to_prompt_stack_content_delta( + self, content_delta: ContentBlockDeltaEvent + ) -> TextDeltaMessageContent: + index = content_delta.index + + if content_delta.delta.type == "text_delta": + return TextDeltaMessageContent(content_delta.delta.text, index=index) + else: + raise ValueError(f"Unsupported message content delta type : {content_delta.delta.type}") diff --git a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py index 41c91cb65..50e9effe6 100644 --- a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py @@ -1,6 +1,6 @@ from attrs import define, field, Factory from typing import Callable, Optional -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.drivers import OpenAiChatPromptDriver import openai diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 90e5259ac..f42e57081 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -1,14 +1,22 @@ from __future__ import annotations + from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Optional from collections.abc import Iterator -from attrs import define, field, Factory -from griptape.events import StartPromptEvent, FinishPromptEvent, CompletionChunkEvent -from griptape.mixins.serializable_mixin import SerializableMixin -from griptape.utils import PromptStack -from griptape.mixins import ExponentialBackoffMixin +from typing import TYPE_CHECKING, Optional + +from attrs import Factory, define, field + +from griptape.common import ( + BaseDeltaMessageContent, + DeltaMessage, + TextDeltaMessageContent, + PromptStack, + Message, + TextMessageContent, +) +from griptape.events import CompletionChunkEvent, FinishPromptEvent, StartPromptEvent +from griptape.mixins import ExponentialBackoffMixin, SerializableMixin from griptape.tokenizers import BaseTokenizer -from griptape.artifacts import TextArtifact if TYPE_CHECKING: from griptape.structures import Structure @@ -39,38 +47,28 @@ class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): def before_run(self, prompt_stack: PromptStack) -> None: if self.structure: - self.structure.publish_event( - StartPromptEvent( - model=self.model, - token_count=self.tokenizer.count_tokens(self.prompt_stack_to_string(prompt_stack)), - prompt_stack=prompt_stack, - prompt=self.prompt_stack_to_string(prompt_stack), - ) - ) + self.structure.publish_event(StartPromptEvent(model=self.model, prompt_stack=prompt_stack)) - def after_run(self, result: TextArtifact) -> None: + def after_run(self, result: Message) -> None: if self.structure: self.structure.publish_event( FinishPromptEvent( - model=self.model, result=result.value, token_count=self.tokenizer.count_tokens(result.value) + model=self.model, + result=result.value, + input_token_count=result.usage.input_tokens, + output_token_count=result.usage.output_tokens, ) ) - def run(self, prompt_stack: PromptStack) -> TextArtifact: + def run(self, prompt_stack: PromptStack) -> Message: for attempt in self.retrying(): with attempt: self.before_run(prompt_stack) if self.stream: - tokens = [] - completion_chunks = self.try_stream(prompt_stack) - for chunk in completion_chunks: - self.structure.publish_event(CompletionChunkEvent(token=chunk.value)) - tokens.append(chunk.value) - result = TextArtifact(value="".join(tokens).strip()) + result = self.__process_stream(prompt_stack) else: - result = self.try_run(prompt_stack) - result.value = result.value.strip() + result = self.__process_run(prompt_stack) self.after_run(result) @@ -90,20 +88,59 @@ def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: """ prompt_lines = [] - for i in prompt_stack.inputs: + for i in prompt_stack.messages: + content = i.to_text() if i.is_user(): - prompt_lines.append(f"User: {i.content}") + prompt_lines.append(f"User: {content}") elif i.is_assistant(): - prompt_lines.append(f"Assistant: {i.content}") + prompt_lines.append(f"Assistant: {content}") else: - prompt_lines.append(i.content) + prompt_lines.append(content) prompt_lines.append("Assistant:") return "\n\n".join(prompt_lines) @abstractmethod - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: ... + def try_run(self, prompt_stack: PromptStack) -> Message: ... @abstractmethod - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: ... + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: ... + + def __process_run(self, prompt_stack: PromptStack) -> Message: + result = self.try_run(prompt_stack) + + return result + + def __process_stream(self, prompt_stack: PromptStack) -> Message: + delta_contents: dict[int, list[BaseDeltaMessageContent]] = {} + usage = DeltaMessage.Usage() + + # Aggregate all content deltas from the stream + deltas = self.try_stream(prompt_stack) + for delta in deltas: + usage += delta.usage + + if delta.content is not None: + if delta.content.index in delta_contents: + delta_contents[delta.content.index].append(delta.content) + else: + delta_contents[delta.content.index] = [delta.content] + + if isinstance(delta.content, TextDeltaMessageContent): + self.structure.publish_event(CompletionChunkEvent(token=delta.content.text)) + + # Build a complete content from the content deltas + content = [] + for deltas in delta_contents.values(): + text_deltas = [delta for delta in deltas if isinstance(delta, TextDeltaMessageContent)] + if text_deltas: + content.append(TextMessageContent.from_deltas(text_deltas)) + + result = Message( + content=content, + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens), + ) + + return result diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index f4a306ebe..331c2c039 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -4,8 +4,17 @@ from attrs import define, field, Factory from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver -from griptape.utils import PromptStack, import_optional_dependency -from griptape.tokenizers import BaseTokenizer, CohereTokenizer +from griptape.tokenizers import CohereTokenizer +from griptape.common import ( + PromptStack, + Message, + DeltaMessage, + TextMessageContent, + BaseMessageContent, + TextDeltaMessageContent, +) +from griptape.utils import import_optional_dependency +from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: from cohere import Client @@ -29,41 +38,71 @@ class CoherePromptDriver(BasePromptDriver): default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True) ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: result = self.client.chat(**self._base_params(prompt_stack)) + usage = result.meta.tokens - return TextArtifact(value=result.text) + return Message( + content=[TextMessageContent(TextArtifact(result.text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: result = self.client.chat_stream(**self._base_params(prompt_stack)) for event in result: if event.event_type == "text-generation": - yield TextArtifact(value=event.text) + yield DeltaMessage(content=TextDeltaMessageContent(event.text, index=0)) + elif event.event_type == "stream-end": + usage = event.response.meta.tokens - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - if prompt_input.is_system(): - return {"role": "SYSTEM", "text": prompt_input.content} - elif prompt_input.is_user(): - return {"role": "USER", "text": prompt_input.content} - else: - return {"role": "ASSISTANT", "text": prompt_input.content} + yield DeltaMessage( + usage=DeltaMessage.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens) + ) + + def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: + return [ + { + "role": self.__to_role(message), + "content": [self.__prompt_stack_content_message_content(content) for content in message.content], + } + for message in messages + ] def _base_params(self, prompt_stack: PromptStack) -> dict: - user_message = prompt_stack.inputs[-1].content + last_input = prompt_stack.messages[-1] + user_message = last_input.to_text() - history_messages = [ - self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs[:-1] if input.content - ] + history_messages = self._prompt_stack_messages_to_messages( + [message for message in prompt_stack.messages[:-1] if not message.is_system()] + ) - params = { + system_messages = prompt_stack.system_messages + if system_messages: + preamble = system_messages[0].to_text() + else: + preamble = None + + return { "message": user_message, + "chat_history": history_messages, "temperature": self.temperature, "stop_sequences": self.tokenizer.stop_sequences, "max_tokens": self.max_tokens, + **({"preamble": preamble} if preamble else {}), } - if history_messages: - params["chat_history"] = history_messages + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"text": content.artifact.to_text()} + else: + raise ValueError(f"Unsupported content type: {type(content)}") - return params + def __to_role(self, message: Message) -> str: + if message.is_system(): + return "SYSTEM" + elif message.is_user(): + return "USER" + else: + return "CHATBOT" diff --git a/griptape/drivers/prompt/dummy_prompt_driver.py b/griptape/drivers/prompt/dummy_prompt_driver.py index a55ecd4fe..72757624d 100644 --- a/griptape/drivers/prompt/dummy_prompt_driver.py +++ b/griptape/drivers/prompt/dummy_prompt_driver.py @@ -1,10 +1,12 @@ +from __future__ import annotations from collections.abc import Iterator -from attrs import field, Factory, define -from griptape.tokenizers import DummyTokenizer + +from attrs import Factory, define, field + +from griptape.common import PromptStack, Message, DeltaMessage from griptape.drivers import BasePromptDriver -from griptape.artifacts import TextArtifact from griptape.exceptions import DummyException -from griptape.utils.prompt_stack import PromptStack +from griptape.tokenizers import DummyTokenizer @define @@ -12,11 +14,8 @@ class DummyPromptDriver(BasePromptDriver): model: None = field(init=False, default=None, kw_only=True) tokenizer: DummyTokenizer = field(default=Factory(lambda: DummyTokenizer()), kw_only=True) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: raise DummyException(__class__.__name__, "try_run") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: raise DummyException(__class__.__name__, "try_stream") - - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - raise DummyException(__class__.__name__, "_prompt_stack_input_to_message") diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 67bc19e24..ff4b07a93 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -1,15 +1,27 @@ from __future__ import annotations + from collections.abc import Iterator -from typing import TYPE_CHECKING, Optional, Any -from attrs import define, field, Factory -from griptape.utils import PromptStack, import_optional_dependency +from typing import TYPE_CHECKING, Any, Optional + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact +from griptape.common import ( + BaseMessageContent, + DeltaMessage, + TextDeltaMessageContent, + ImageMessageContent, + PromptStack, + Message, + TextMessageContent, +) from griptape.drivers import BasePromptDriver -from griptape.tokenizers import GoogleTokenizer, BaseTokenizer +from griptape.tokenizers import BaseTokenizer, GoogleTokenizer +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from google.generativeai import GenerativeModel - from google.generativeai.types import ContentDict + from google.generativeai.types import ContentDict, GenerateContentResponse @define @@ -33,12 +45,12 @@ class GooglePromptDriver(BasePromptDriver): top_p: Optional[float] = field(default=None, kw_only=True, metadata={"serializable": True}) top_k: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig - inputs = self._prompt_stack_to_model_input(prompt_stack) - response = self.model_client.generate_content( - inputs, + messages = self._prompt_stack_to_messages(prompt_stack) + response: GenerateContentResponse = self.model_client.generate_content( + messages, generation_config=GenerationConfig( stop_sequences=self.tokenizer.stop_sequences, max_output_tokens=self.max_tokens, @@ -48,14 +60,22 @@ def try_run(self, prompt_stack: PromptStack) -> TextArtifact: ), ) - return TextArtifact(value=response.text) + usage_metadata = response.usage_metadata - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + return Message( + content=[TextMessageContent(TextArtifact(response.text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage( + input_tokens=usage_metadata.prompt_token_count, output_tokens=usage_metadata.candidates_token_count + ), + ) + + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig - inputs = self._prompt_stack_to_model_input(prompt_stack) - response = self.model_client.generate_content( - inputs, + messages = self._prompt_stack_to_messages(prompt_stack) + response: Iterator[GenerateContentResponse] = self.model_client.generate_content( + messages, stream=True, generation_config=GenerationConfig( stop_sequences=self.tokenizer.stop_sequences, @@ -66,16 +86,27 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: ), ) + prompt_token_count = None for chunk in response: - yield TextArtifact(value=chunk.text) - - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - parts = [prompt_input.content] - - if prompt_input.is_assistant(): - return {"role": "model", "parts": parts} - else: - return {"role": "user", "parts": parts} + usage_metadata = chunk.usage_metadata + + # Only want to output the prompt token count once since it is static each chunk + if prompt_token_count is None: + prompt_token_count = usage_metadata.prompt_token_count + yield DeltaMessage( + content=TextDeltaMessageContent(chunk.text), + role=Message.ASSISTANT_ROLE, + usage=DeltaMessage.Usage( + input_tokens=usage_metadata.prompt_token_count, + output_tokens=usage_metadata.candidates_token_count, + ), + ) + else: + yield DeltaMessage( + content=TextDeltaMessageContent(chunk.text), + role=Message.ASSISTANT_ROLE, + usage=DeltaMessage.Usage(output_tokens=usage_metadata.candidates_token_count), + ) def _default_model_client(self) -> GenerativeModel: genai = import_optional_dependency("google.generativeai") @@ -83,20 +114,35 @@ def _default_model_client(self) -> GenerativeModel: return genai.GenerativeModel(self.model) - def _prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> list[ContentDict]: + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: inputs = [ - self.__to_content_dict(prompt_input) for prompt_input in prompt_stack.inputs if not prompt_input.is_system() + {"role": self.__to_role(message), "parts": self.__to_content(message)} + for message in prompt_stack.messages + if not message.is_system() ] # Gemini does not have the notion of a system message, so we insert it as part of the first message in the history. - system = next((i for i in prompt_stack.inputs if i.is_system()), None) - if system is not None: - inputs[0]["parts"].insert(0, system.content) + system_messages = prompt_stack.system_messages + if system_messages: + inputs[0]["parts"].insert(0, system_messages[0].to_text()) return inputs - def __to_content_dict(self, prompt_input: PromptStack.Input) -> ContentDict: + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> ContentDict | str: ContentDict = import_optional_dependency("google.generativeai.types").ContentDict - message = self._prompt_stack_input_to_message(prompt_input) - return ContentDict(message) + if isinstance(content, TextMessageContent): + return content.artifact.to_text() + elif isinstance(content, ImageMessageContent): + return ContentDict(mime_type=content.artifact.mime_type, data=content.artifact.value) + else: + raise ValueError(f"Unsupported content type: {type(content)}") + + def __to_role(self, message: Message) -> str: + if message.is_assistant(): + return "model" + else: + return "user" + + def __to_content(self, message: Message) -> list[ContentDict | str]: + return [self.__prompt_stack_content_message_content(content) for content in message.content] diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index 3edd252cb..f327010c4 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -5,10 +5,10 @@ from attrs import Factory, define, field -from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer -from griptape.utils import PromptStack, import_optional_dependency +from griptape.common import PromptStack, Message, DeltaMessage, TextDeltaMessageContent +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from huggingface_hub import InferenceClient @@ -47,37 +47,54 @@ class HuggingFaceHubPromptDriver(BasePromptDriver): kw_only=True, ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( prompt, return_full_text=False, max_new_tokens=self.max_tokens, **self.params ) + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + output_tokens = len(self.tokenizer.tokenizer.encode(response)) - return TextArtifact(value=response) + return Message( + content=response, + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( prompt, return_full_text=False, max_new_tokens=self.max_tokens, stream=True, **self.params ) + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + + full_text = "" for token in response: - yield TextArtifact(value=token) + full_text += token + yield DeltaMessage(content=TextDeltaMessageContent(token, index=0)) - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - return {"role": prompt_input.role, "content": prompt_input.content} + output_tokens = len(self.tokenizer.tokenizer.encode(full_text)) + yield DeltaMessage(usage=DeltaMessage.Usage(input_tokens=input_tokens, output_tokens=output_tokens)) def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + messages = [] + for message in prompt_stack.messages: + if len(message.content) == 1: + messages.append({"role": message.role, "content": message.to_text()}) + else: + raise ValueError("Invalid input content length.") + + return messages + def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: - tokens = self.tokenizer.tokenizer.apply_chat_template( - [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], - add_generation_prompt=True, - tokenize=True, - ) + messages = self._prompt_stack_to_messages(prompt_stack) + tokens = self.tokenizer.tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=True) if isinstance(tokens, list): return tokens diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index 4fa291877..6dabc3e20 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -1,13 +1,15 @@ from __future__ import annotations -from collections.abc import Iterator +from collections.abc import Iterator from typing import TYPE_CHECKING + from attrs import Factory, define, field from griptape.artifacts import TextArtifact +from griptape.common import DeltaMessage, PromptStack, Message, TextMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer -from griptape.utils import PromptStack, import_optional_dependency +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from transformers import TextGenerationPipeline @@ -40,43 +42,47 @@ class HuggingFacePipelinePromptDriver(BasePromptDriver): ) ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs] + def try_run(self, prompt_stack: PromptStack) -> Message: + messages = self._prompt_stack_to_messages(prompt_stack) result = self.pipe( - messages, - max_new_tokens=self.max_tokens, - tokenizer=self.tokenizer.tokenizer, - stop_strings=self.tokenizer.stop_sequences, - temperature=self.temperature, - do_sample=True, + messages, max_new_tokens=self.max_tokens, temperature=self.temperature, do_sample=True, **self.params ) if isinstance(result, list): if len(result) == 1: generated_text = result[0]["generated_text"][-1]["content"] - return TextArtifact(value=generated_text) + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + output_tokens = len(self.tokenizer.tokenizer.encode(generated_text)) + + return Message( + content=[TextMessageContent(TextArtifact(generated_text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), + ) else: raise Exception("completion with more than one choice is not supported yet") else: raise Exception("invalid output format") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: raise NotImplementedError("streaming is not supported") def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - return {"role": prompt_input.role, "content": prompt_input.content} + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + messages = [] + + for message in prompt_stack.messages: + messages.append({"role": message.role, "content": message.to_text()}) + + return messages def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: - tokens = self.tokenizer.tokenizer.apply_chat_template( - [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], - add_generation_prompt=True, - tokenize=True, - ) + messages = self._prompt_stack_to_messages(prompt_stack) + tokens = self.tokenizer.tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=True) if isinstance(tokens, list): return tokens diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py index b21176e82..5a78abf29 100644 --- a/griptape/drivers/prompt/ollama_prompt_driver.py +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -5,8 +5,11 @@ from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver from griptape.tokenizers.base_tokenizer import BaseTokenizer -from griptape.utils import PromptStack, import_optional_dependency +from griptape.common import PromptStack, TextMessageContent +from griptape.utils import import_optional_dependency from griptape.tokenizers import SimpleTokenizer +from griptape.common import Message, DeltaMessage, TextDeltaMessageContent +from griptape.common import ImageMessageContent if TYPE_CHECKING: from ollama import Client @@ -46,24 +49,47 @@ class OllamaPromptDriver(BasePromptDriver): kw_only=True, ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: response = self.client.chat(**self._base_params(prompt_stack)) if isinstance(response, dict): - return TextArtifact(value=response["message"]["content"]) + return Message( + content=[TextMessageContent(TextArtifact(value=response["message"]["content"]))], + role=Message.ASSISTANT_ROLE, + ) else: raise Exception("invalid model response") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: stream = self.client.chat(**self._base_params(prompt_stack), stream=True) if isinstance(stream, Iterator): for chunk in stream: - yield TextArtifact(value=chunk["message"]["content"]) + yield DeltaMessage(content=TextDeltaMessageContent(chunk["message"]["content"])) else: raise Exception("invalid model response") def _base_params(self, prompt_stack: PromptStack) -> dict: - messages = [{"role": input.role, "content": input.content} for input in prompt_stack.inputs] + messages = self._prompt_stack_to_messages(prompt_stack) return {"messages": messages, "model": self.model, "options": self.options} + + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + return [ + { + "role": message.role, + "content": message.to_text(), + **( + { + "images": [ + content.artifact.base64 + for content in message.content + if isinstance(content, ImageMessageContent) + ] + } + if any(isinstance(content, ImageMessageContent) for content in message.content) + else {} + ), + } + for message in prompt_stack.messages + ] diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index 9545bd45a..e1e046d11 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -1,12 +1,28 @@ from __future__ import annotations -from typing import Optional, Literal + from collections.abc import Iterator +from typing import Literal, Optional, TYPE_CHECKING + import openai -from attrs import define, field, Factory +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack +from griptape.common import ( + BaseMessageContent, + DeltaMessage, + TextDeltaMessageContent, + ImageMessageContent, + PromptStack, + Message, + TextMessageContent, +) from griptape.drivers import BasePromptDriver -from griptape.tokenizers import OpenAiTokenizer, BaseTokenizer +from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer + + +if TYPE_CHECKING: + from openai.types.chat.chat_completion_message import ChatCompletionMessage + from openai.types.chat.chat_completion_chunk import ChoiceDelta @define @@ -57,57 +73,105 @@ class OpenAiChatPromptDriver(BasePromptDriver): kw_only=True, ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: result = self.client.chat.completions.create(**self._base_params(prompt_stack)) if len(result.choices) == 1: - return TextArtifact(value=result.choices[0].message.content.strip()) + message = result.choices[0].message + + return Message( + content=[self.__message_to_prompt_stack_content(message)], + role=message.role, + usage=Message.Usage( + input_tokens=result.usage.prompt_tokens, output_tokens=result.usage.completion_tokens + ), + ) else: raise Exception("Completion with more than one choice is not supported yet.") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - result = self.client.chat.completions.create(**self._base_params(prompt_stack), stream=True) + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: + result = self.client.chat.completions.create( + **self._base_params(prompt_stack), stream=True, stream_options={"include_usage": True} + ) for chunk in result: - if len(chunk.choices) == 1: - delta = chunk.choices[0].delta - else: - raise Exception("Completion with more than one choice is not supported yet.") - - if delta.content is not None: - delta_content = delta.content - - yield TextArtifact(value=delta_content) - - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - content = prompt_input.content - - if prompt_input.is_system(): - return {"role": "system", "content": content} - elif prompt_input.is_assistant(): - return {"role": "assistant", "content": content} - else: - return {"role": "user", "content": content} + if chunk.usage is not None: + yield DeltaMessage( + usage=DeltaMessage.Usage( + input_tokens=chunk.usage.prompt_tokens, output_tokens=chunk.usage.completion_tokens + ) + ) + elif chunk.choices is not None: + if len(chunk.choices) == 1: + choice = chunk.choices[0] + delta = choice.delta + + yield DeltaMessage(content=self.__message_delta_to_prompt_stack_content_delta(delta)) + else: + raise Exception("Completion with more than one choice is not supported yet.") + + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + return [ + {"role": self.__to_role(message), "content": self.__to_content(message)} + for message in prompt_stack.messages + ] def _base_params(self, prompt_stack: PromptStack) -> dict: params = { "model": self.model, "temperature": self.temperature, - "stop": self.tokenizer.stop_sequences, "user": self.user, "seed": self.seed, + **({"stop": self.tokenizer.stop_sequences} if self.tokenizer.stop_sequences else {}), + **({"max_tokens": self.max_tokens} if self.max_tokens is not None else {}), } if self.response_format == "json_object": params["response_format"] = {"type": "json_object"} - # JSON mode still requires a system input instructing the LLM to output JSON. - prompt_stack.add_system_input("Provide your response as a valid JSON object.") + # JSON mode still requires a system message instructing the LLM to output JSON. + prompt_stack.add_system_message("Provide your response as a valid JSON object.") - messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs] - - if self.max_tokens is not None: - params["max_tokens"] = self.max_tokens + messages = self._prompt_stack_to_messages(prompt_stack) params["messages"] = messages return params + + def __to_role(self, message: Message) -> str: + if message.is_system(): + return "system" + elif message.is_assistant(): + return "assistant" + else: + return "user" + + def __to_content(self, message: Message) -> str | list[dict]: + if all(isinstance(content, TextMessageContent) for content in message.content): + return message.to_text() + else: + return [self.__prompt_stack_content_message_content(content) for content in message.content] + + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"type": "text", "text": content.artifact.to_text()} + elif isinstance(content, ImageMessageContent): + return { + "type": "image_url", + "image_url": {"url": f"data:{content.artifact.mime_type};base64,{content.artifact.base64}"}, + } + else: + raise ValueError(f"Unsupported content type: {type(content)}") + + def __message_to_prompt_stack_content(self, message: ChatCompletionMessage) -> BaseMessageContent: + if message.content is not None: + return TextMessageContent(TextArtifact(message.content)) + else: + raise ValueError(f"Unsupported message type: {message}") + + def __message_delta_to_prompt_stack_content_delta(self, content_delta: ChoiceDelta) -> TextDeltaMessageContent: + if content_delta.content is None: + return TextDeltaMessageContent("") + else: + delta_content = content_delta.content + + return TextDeltaMessageContent(delta_content) diff --git a/griptape/engines/extraction/csv_extraction_engine.py b/griptape/engines/extraction/csv_extraction_engine.py index fe4d0e6c7..6fe9bb879 100644 --- a/griptape/engines/extraction/csv_extraction_engine.py +++ b/griptape/engines/extraction/csv_extraction_engine.py @@ -4,7 +4,8 @@ import io from attrs import field, Factory, define from griptape.artifacts import TextArtifact, CsvRowArtifact, ListArtifact, ErrorArtifact -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.common.prompt_stack.messages.message import Message from griptape.engines import BaseExtractionEngine from griptape.utils import J2 from griptape.rules import Ruleset @@ -63,9 +64,7 @@ def _extract_rec( if self.prompt_driver.tokenizer.count_input_tokens_left(full_text) >= self.min_response_tokens: rows.extend( self.text_to_csv_rows( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(full_text, role=PromptStack.USER_ROLE)]) - ).value, + self.prompt_driver.run(PromptStack(messages=[Message(full_text, role=Message.USER_ROLE)])).value, column_names, ) ) @@ -81,9 +80,7 @@ def _extract_rec( rows.extend( self.text_to_csv_rows( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(partial_text, role=PromptStack.USER_ROLE)]) - ).value, + self.prompt_driver.run(PromptStack(messages=[Message(partial_text, role=Message.USER_ROLE)])).value, column_names, ) ) diff --git a/griptape/engines/extraction/json_extraction_engine.py b/griptape/engines/extraction/json_extraction_engine.py index 05db19d40..830092dab 100644 --- a/griptape/engines/extraction/json_extraction_engine.py +++ b/griptape/engines/extraction/json_extraction_engine.py @@ -3,9 +3,10 @@ import json from attrs import field, Factory, define from griptape.artifacts import TextArtifact, ListArtifact, ErrorArtifact +from griptape.common.prompt_stack.messages.message import Message from griptape.engines import BaseExtractionEngine from griptape.utils import J2 -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.rules import Ruleset @@ -58,9 +59,7 @@ def _extract_rec( if self.prompt_driver.tokenizer.count_input_tokens_left(full_text) >= self.min_response_tokens: extractions.extend( self.json_to_text_artifacts( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(full_text, role=PromptStack.USER_ROLE)]) - ).value + self.prompt_driver.run(PromptStack(messages=[Message(full_text, role=Message.USER_ROLE)])).value ) ) @@ -75,9 +74,7 @@ def _extract_rec( extractions.extend( self.json_to_text_artifacts( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(partial_text, role=PromptStack.USER_ROLE)]) - ).value + self.prompt_driver.run(PromptStack(messages=[Message(partial_text, role=Message.USER_ROLE)])).value ) ) diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py index 8e9b42e93..13563970d 100644 --- a/griptape/engines/rag/modules/base_rag_module.py +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -4,7 +4,7 @@ from attrs import define, field, Factory -from griptape.utils import PromptStack +from griptape.common import PromptStack, Message @define(kw_only=True) @@ -15,8 +15,5 @@ class BaseRagModule(ABC): def generate_query_prompt_stack(self, system_prompt: str, query: str) -> PromptStack: return PromptStack( - inputs=[ - PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(query, role=PromptStack.USER_ROLE), - ] + messages=[Message(system_prompt, role=Message.SYSTEM_ROLE), Message(query, role=Message.USER_ROLE)] ) diff --git a/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py b/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py index 9e7c3b08f..26d95bdd1 100644 --- a/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py +++ b/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py @@ -1,5 +1,6 @@ from typing import Callable from attrs import define, field, Factory +from griptape.artifacts.text_artifact import TextArtifact from griptape.drivers import BasePromptDriver from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseGenerationRagModule @@ -40,7 +41,12 @@ def run(self, context: RagContext) -> RagContext: break - context.output = self.prompt_driver.run(self.generate_query_prompt_stack(system_prompt, query)) + output = self.prompt_driver.run(self.generate_query_prompt_stack(system_prompt, query)).to_artifact() + + if isinstance(output, TextArtifact): + context.output = output + else: + raise ValueError("Prompt driver did not return a TextArtifact") return context diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 9d3e8db78..51259e444 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -2,7 +2,8 @@ from attrs import define, Factory, field from griptape.artifacts import TextArtifact, ListArtifact from griptape.chunkers import BaseChunker, TextChunker -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.common.prompt_stack.messages.message import Message from griptape.drivers import BasePromptDriver from griptape.engines import BaseSummaryEngine from griptape.utils import J2 @@ -60,14 +61,19 @@ def summarize_artifacts_rec( self.prompt_driver.tokenizer.count_input_tokens_left(user_prompt + system_prompt) >= self.min_response_tokens ): - return self.prompt_driver.run( + result = self.prompt_driver.run( PromptStack( - inputs=[ - PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(user_prompt, role=PromptStack.USER_ROLE), + messages=[ + Message(system_prompt, role=Message.SYSTEM_ROLE), + Message(user_prompt, role=Message.USER_ROLE), ] ) - ) + ).to_artifact() + + if isinstance(result, TextArtifact): + return result + else: + raise ValueError("Prompt driver did not return a TextArtifact") else: chunks = self.chunker.chunk(artifacts_text) @@ -77,9 +83,9 @@ def summarize_artifacts_rec( chunks[1:], self.prompt_driver.run( PromptStack( - inputs=[ - PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(partial_text, role=PromptStack.USER_ROLE), + messages=[ + Message(system_prompt, role=Message.SYSTEM_ROLE), + Message(partial_text, role=Message.USER_ROLE), ] ) ).value, diff --git a/griptape/events/base_prompt_event.py b/griptape/events/base_prompt_event.py index b9dcd0c57..4a44599cc 100644 --- a/griptape/events/base_prompt_event.py +++ b/griptape/events/base_prompt_event.py @@ -7,4 +7,3 @@ @define class BasePromptEvent(BaseEvent, ABC): model: str = field(kw_only=True, metadata={"serializable": True}) - token_count: int = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/events/finish_prompt_event.py b/griptape/events/finish_prompt_event.py index 83bc1b9ef..79e338871 100644 --- a/griptape/events/finish_prompt_event.py +++ b/griptape/events/finish_prompt_event.py @@ -1,7 +1,10 @@ from attrs import define, field +from typing import Optional from griptape.events.base_prompt_event import BasePromptEvent @define class FinishPromptEvent(BasePromptEvent): result: str = field(kw_only=True, metadata={"serializable": True}) + input_token_count: Optional[float] = field(kw_only=True, metadata={"serializable": True}) + output_token_count: Optional[float] = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/events/start_prompt_event.py b/griptape/events/start_prompt_event.py index 7ab418adb..35dae95d6 100644 --- a/griptape/events/start_prompt_event.py +++ b/griptape/events/start_prompt_event.py @@ -5,10 +5,9 @@ from griptape.events.base_prompt_event import BasePromptEvent if TYPE_CHECKING: - from griptape.utils import PromptStack + from griptape.common import PromptStack @define class StartPromptEvent(BasePromptEvent): prompt_stack: PromptStack = field(kw_only=True, metadata={"serializable": True}) - prompt: str = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/memory/structure/base_conversation_memory.py b/griptape/memory/structure/base_conversation_memory.py index f8cc51743..a8133d64b 100644 --- a/griptape/memory/structure/base_conversation_memory.py +++ b/griptape/memory/structure/base_conversation_memory.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Optional from attrs import define, field from griptape.memory.structure import Run -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.mixins import SerializableMixin from abc import ABC, abstractmethod @@ -47,7 +47,7 @@ def try_add_run(self, run: Run) -> None: ... def to_prompt_stack(self, last_n: Optional[int] = None) -> PromptStack: ... def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = None) -> PromptStack: - """Add the Conversation Memory runs to the Prompt Stack by modifying the inputs in place. + """Add the Conversation Memory runs to the Prompt Stack by modifying the messages in place. If autoprune is enabled, this will fit as many Conversation Memory runs into the Prompt Stack as possible without exceeding the token limit. @@ -67,15 +67,15 @@ def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = # Try to determine how many Conversation Memory runs we can # fit into the Prompt Stack without exceeding the token limit. while should_prune and num_runs_to_fit_in_prompt > 0: - temp_stack.inputs = prompt_stack.inputs.copy() + temp_stack.messages = prompt_stack.messages.copy() # Add n runs from Conversation Memory. # Where we insert into the Prompt Stack doesn't matter here # since we only care about the total token count. - memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).inputs - temp_stack.inputs.extend(memory_inputs) + memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).messages + temp_stack.messages.extend(memory_inputs) - # Convert the prompt stack into tokens left. + # Convert the Prompt Stack into tokens left. tokens_left = prompt_driver.tokenizer.count_input_tokens_left( prompt_driver.prompt_stack_to_string(temp_stack) ) @@ -87,10 +87,10 @@ def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = num_runs_to_fit_in_prompt -= 1 if num_runs_to_fit_in_prompt: - memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).inputs + memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).messages if index: - prompt_stack.inputs[index:index] = memory_inputs + prompt_stack.messages[index:index] = memory_inputs else: - prompt_stack.inputs.extend(memory_inputs) + prompt_stack.messages.extend(memory_inputs) return prompt_stack diff --git a/griptape/memory/structure/conversation_memory.py b/griptape/memory/structure/conversation_memory.py index 94e73d80c..42d160abd 100644 --- a/griptape/memory/structure/conversation_memory.py +++ b/griptape/memory/structure/conversation_memory.py @@ -2,7 +2,7 @@ from attrs import define from typing import Optional from griptape.memory.structure import Run, BaseConversationMemory -from griptape.utils import PromptStack +from griptape.common import PromptStack @define @@ -18,6 +18,6 @@ def to_prompt_stack(self, last_n: Optional[int] = None) -> PromptStack: prompt_stack = PromptStack() runs = self.runs[-last_n:] if last_n else self.runs for run in runs: - prompt_stack.add_user_input(run.input) - prompt_stack.add_assistant_input(run.output) + prompt_stack.add_user_message(run.input) + prompt_stack.add_assistant_message(run.output) return prompt_stack diff --git a/griptape/memory/structure/run.py b/griptape/memory/structure/run.py index c5a2b9b55..b91df2ae9 100644 --- a/griptape/memory/structure/run.py +++ b/griptape/memory/structure/run.py @@ -1,10 +1,11 @@ import uuid from attrs import define, field, Factory +from griptape.artifacts.base_artifact import BaseArtifact from griptape.mixins import SerializableMixin @define class Run(SerializableMixin): id: str = field(default=Factory(lambda: uuid.uuid4().hex), kw_only=True, metadata={"serializable": True}) - input: str = field(kw_only=True, metadata={"serializable": True}) - output: str = field(kw_only=True, metadata={"serializable": True}) + input: BaseArtifact = field(kw_only=True, metadata={"serializable": True}) + output: BaseArtifact = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/memory/structure/summary_conversation_memory.py b/griptape/memory/structure/summary_conversation_memory.py index e4d5597d5..b88a4b4e6 100644 --- a/griptape/memory/structure/summary_conversation_memory.py +++ b/griptape/memory/structure/summary_conversation_memory.py @@ -2,7 +2,9 @@ import logging from typing import TYPE_CHECKING, Optional from attrs import define, field, Factory -from griptape.utils import J2, PromptStack +from griptape.common.prompt_stack.messages.message import Message +from griptape.utils import J2 +from griptape.common import PromptStack from griptape.memory.structure import ConversationMemory if TYPE_CHECKING: @@ -37,11 +39,11 @@ def prompt_driver(self, value: BasePromptDriver) -> None: def to_prompt_stack(self, last_n: Optional[int] = None) -> PromptStack: stack = PromptStack() if self.summary: - stack.add_user_input(self.summary_template_generator.render(summary=self.summary)) + stack.add_user_message(self.summary_template_generator.render(summary=self.summary)) for r in self.unsummarized_runs(last_n): - stack.add_user_input(r.input) - stack.add_assistant_input(r.output) + stack.add_user_message(r.input) + stack.add_assistant_message(r.output) return stack @@ -73,7 +75,7 @@ def summarize_runs(self, previous_summary: str | None, runs: list[Run]) -> str | if len(runs) > 0: summary = self.summarize_conversation_template_generator.render(summary=previous_summary, runs=runs) return self.prompt_driver.run( - prompt_stack=PromptStack(inputs=[PromptStack.Input(summary, role=PromptStack.USER_ROLE)]) + prompt_stack=PromptStack(messages=[Message(summary, role=Message.USER_ROLE)]) ).to_text() else: return previous_summary diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 6ba23d6fe..1099e1bf7 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -105,7 +105,7 @@ def _resolve_types(cls, attrs_cls: type) -> None: # These modules are required to avoid `NameError`s when resolving types. from griptape.drivers import BaseConversationMemoryDriver, BasePromptDriver from griptape.structures import Structure - from griptape.utils import PromptStack + from griptape.common import PromptStack, Message from griptape.tokenizers.base_tokenizer import BaseTokenizer from typing import Any @@ -116,7 +116,7 @@ def _resolve_types(cls, attrs_cls: type) -> None: attrs_cls, localns={ "PromptStack": PromptStack, - "Input": PromptStack.Input, + "Usage": Message.Usage, "Structure": Structure, "BaseConversationMemoryDriver": BaseConversationMemoryDriver, "BasePromptDriver": BasePromptDriver, diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 2840d5c46..598aae37c 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -1,10 +1,12 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, Optional, Callable from attrs import define, field +from griptape.artifacts.text_artifact import TextArtifact from griptape.tools import BaseTool from griptape.memory.structure import Run from griptape.structures import Structure from griptape.tasks import PromptTask, ToolkitTask +from griptape.artifacts import BaseArtifact if TYPE_CHECKING: from griptape.tasks import BaseTask @@ -12,7 +14,9 @@ @define class Agent(Structure): - input_template: str = field(default=PromptTask.DEFAULT_INPUT_TEMPLATE) + input: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact] = field( + default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value="") + ) tools: list[BaseTool] = field(factory=list, kw_only=True) max_meta_memory_entries: Optional[int] = field(default=20, kw_only=True) fail_fast: bool = field(default=False, kw_only=True) @@ -26,11 +30,9 @@ def __attrs_post_init__(self) -> None: super().__attrs_post_init__() if len(self.tasks) == 0: if self.tools: - task = ToolkitTask( - self.input_template, tools=self.tools, max_meta_memory_entries=self.max_meta_memory_entries - ) + task = ToolkitTask(self.input, tools=self.tools, max_meta_memory_entries=self.max_meta_memory_entries) else: - task = PromptTask(self.input_template, max_meta_memory_entries=self.max_meta_memory_entries) + task = PromptTask(self.input, max_meta_memory_entries=self.max_meta_memory_entries) self.add_task(task) @@ -56,12 +58,7 @@ def try_run(self, *args) -> Agent: self.task.execute() if self.conversation_memory and self.output is not None: - if isinstance(self.task.input, tuple): - input_text = self.task.input[0].to_text() - else: - input_text = self.task.input.to_text() - - run = Run(input=input_text, output=self.task.output.to_text()) + run = Run(input=self.input_task.input, output=self.output) self.conversation_memory.add_run(run) diff --git a/griptape/structures/pipeline.py b/griptape/structures/pipeline.py index 4fc784974..408a42225 100644 --- a/griptape/structures/pipeline.py +++ b/griptape/structures/pipeline.py @@ -46,12 +46,7 @@ def try_run(self, *args) -> Pipeline: self.__run_from_task(self.input_task) if self.conversation_memory and self.output is not None: - if isinstance(self.input_task.input, tuple): - input_text = self.input_task.input[0].to_text() - else: - input_text = self.input_task.input.to_text() - - run = Run(input=input_text, output=self.output.to_text()) + run = Run(input=self.input_task.input, output=self.output) self.conversation_memory.add_run(run) diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 204650c41..3689f7330 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -120,12 +120,7 @@ def try_run(self, *args) -> Workflow: break if self.conversation_memory and self.output is not None: - if isinstance(self.input_task.input, tuple): - input_text = self.input_task.input[0].to_text() - else: - input_text = self.input_task.input.to_text() - - run = Run(input=input_text, output=self.output_task.output.to_text()) + run = Run(input=self.input_task.input, output=self.output) self.conversation_memory.add_run(run) diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index 694a5050d..f10899f76 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -1,10 +1,15 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Callable -from attrs import define, field, Factory -from griptape.utils import PromptStack -from griptape.utils import J2 -from griptape.tasks import BaseTextInputTask + +from typing import TYPE_CHECKING, Callable, Optional + +from attrs import Factory, define, field + from griptape.artifacts import BaseArtifact +from griptape.common import PromptStack +from griptape.tasks import BaseTask +from griptape.utils import J2 +from griptape.artifacts import TextArtifact, ListArtifact +from griptape.mixins import RuleMixin if TYPE_CHECKING: from griptape.drivers import BasePromptDriver @@ -12,11 +17,23 @@ @define -class PromptTask(BaseTextInputTask): +class PromptTask(RuleMixin, BaseTask): _prompt_driver: Optional[BasePromptDriver] = field(default=None, kw_only=True, alias="prompt_driver") generate_system_template: Callable[[PromptTask], str] = field( default=Factory(lambda self: self.default_system_template_generator, takes_self=True), kw_only=True ) + _input: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact] = field( + default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value=""), + alias="input", + ) + + @property + def input(self) -> BaseArtifact: + return self._process_task_input(self._input) + + @input.setter + def input(self, value: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact]) -> None: + self._input = value output: Optional[BaseArtifact] = field(default=None, init=False) @@ -25,12 +42,12 @@ def prompt_stack(self) -> PromptStack: stack = PromptStack() memory = self.structure.conversation_memory - stack.add_system_input(self.generate_system_template(self)) + stack.add_system_message(self.generate_system_template(self)) - stack.add_user_input(self.input.to_text()) + stack.add_user_message(self.input) if self.output: - stack.add_assistant_input(self.output.to_text()) + stack.add_assistant_message(self.output) if memory: # inserting at index 1 to place memory right after system prompt @@ -59,7 +76,35 @@ def default_system_template_generator(self, _: PromptTask) -> str: rulesets=J2("rulesets/rulesets.j2").render(rulesets=self.all_rulesets) ) - def run(self) -> BaseArtifact: - self.output = self.prompt_driver.run(self.prompt_stack) + def before_run(self) -> None: + super().before_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nInput: {self.input.to_text()}") - return self.output + def after_run(self) -> None: + super().after_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nOutput: {self.output.to_text()}") + + def run(self) -> BaseArtifact: + message = self.prompt_driver.run(self.prompt_stack) + + return message.to_artifact() + + def _process_task_input( + self, task_input: str | tuple | list | BaseArtifact | Callable[[BaseTask], BaseArtifact] + ) -> BaseArtifact: + if isinstance(task_input, TextArtifact): + task_input.value = J2().render_from_string(task_input.value, **self.full_context) + + return task_input + elif isinstance(task_input, Callable): + return self._process_task_input(task_input(self)) + elif isinstance(task_input, str): + return self._process_task_input(TextArtifact(task_input)) + elif isinstance(task_input, BaseArtifact): + return task_input + elif isinstance(task_input, list) or isinstance(task_input, tuple): + return ListArtifact([self._process_task_input(elem) for elem in task_input]) + else: + raise ValueError(f"Invalid input type: {type(task_input)} ") diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index c99f9e23f..58300b529 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -10,7 +10,7 @@ from griptape.tasks import ActionsSubtask from griptape.tasks import PromptTask from griptape.utils import J2 -from griptape.utils import PromptStack +from griptape.common import PromptStack if TYPE_CHECKING: from griptape.tools import BaseTool @@ -65,16 +65,16 @@ def prompt_stack(self) -> PromptStack: stack = PromptStack() memory = self.structure.conversation_memory - stack.add_system_input(self.generate_system_template(self)) + stack.add_system_message(self.generate_system_template(self)) - stack.add_user_input(self.input.to_text()) + stack.add_user_message(self.input) if self.output: - stack.add_assistant_input(self.output.to_text()) + stack.add_assistant_message(self.output.to_text()) else: for s in self.subtasks: - stack.add_assistant_input(self.generate_assistant_subtask_template(s)) - stack.add_user_input(self.generate_user_subtask_template(s)) + stack.add_assistant_message(self.generate_assistant_subtask_template(s)) + stack.add_user_message(self.generate_user_subtask_template(s)) if memory: # inserting at index 1 to place memory right after system prompt diff --git a/griptape/tokenizers/amazon_bedrock_tokenizer.py b/griptape/tokenizers/amazon_bedrock_tokenizer.py index 670b5739a..951802d59 100644 --- a/griptape/tokenizers/amazon_bedrock_tokenizer.py +++ b/griptape/tokenizers/amazon_bedrock_tokenizer.py @@ -1,4 +1,5 @@ from __future__ import annotations + from attrs import define, field from griptape.tokenizers.base_tokenizer import BaseTokenizer diff --git a/griptape/tokenizers/huggingface_tokenizer.py b/griptape/tokenizers/huggingface_tokenizer.py index a8312567d..fdebd23da 100644 --- a/griptape/tokenizers/huggingface_tokenizer.py +++ b/griptape/tokenizers/huggingface_tokenizer.py @@ -1,4 +1,5 @@ from __future__ import annotations + from typing import TYPE_CHECKING from attrs import define, field, Factory from griptape.utils import import_optional_dependency diff --git a/griptape/tokenizers/openai_tokenizer.py b/griptape/tokenizers/openai_tokenizer.py index 39a2a033e..a58ec5ce5 100644 --- a/griptape/tokenizers/openai_tokenizer.py +++ b/griptape/tokenizers/openai_tokenizer.py @@ -1,8 +1,11 @@ from __future__ import annotations + import logging -from attrs import define, field, Factory -import tiktoken from typing import Optional + +import tiktoken +from attrs import Factory, define, field + from griptape.tokenizers import BaseTokenizer diff --git a/griptape/tokenizers/voyageai_tokenizer.py b/griptape/tokenizers/voyageai_tokenizer.py index d8fb5adf1..649f6e0cc 100644 --- a/griptape/tokenizers/voyageai_tokenizer.py +++ b/griptape/tokenizers/voyageai_tokenizer.py @@ -1,8 +1,11 @@ from __future__ import annotations -from attrs import define, field, Factory + from typing import TYPE_CHECKING, Optional -from griptape.utils import import_optional_dependency + +from attrs import Factory, define, field + from griptape.tokenizers import BaseTokenizer +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from voyageai import Client diff --git a/griptape/tools/prompt_image_generation_client/tool.py b/griptape/tools/prompt_image_generation_client/tool.py index 50020a1ea..6f4ce0e1f 100644 --- a/griptape/tools/prompt_image_generation_client/tool.py +++ b/griptape/tools/prompt_image_generation_client/tool.py @@ -30,20 +30,15 @@ class PromptImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): Literal( "prompts", description="A detailed list of features and descriptions to include in the generated image.", - ): list[str], - Literal( - "negative_prompts", - description="A detailed list of features and descriptions to avoid in the generated image.", - ): list[str], + ): list[str] } ), } ) def generate_image(self, params: dict[str, dict[str, list[str]]]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] - negative_prompts = params["values"]["negative_prompts"] - output_artifact = self.engine.run(prompts=prompts, negative_prompts=negative_prompts) + output_artifact = self.engine.run(prompts=prompts) if self.output_dir or self.output_file: self._write_to_file(output_artifact) diff --git a/griptape/utils/__init__.py b/griptape/utils/__init__.py index 5ca129993..a84703f39 100644 --- a/griptape/utils/__init__.py +++ b/griptape/utils/__init__.py @@ -8,7 +8,6 @@ from .futures import execute_futures_dict from .futures import execute_futures_list from .token_counter import TokenCounter -from .prompt_stack import PromptStack from .dict_utils import remove_null_values_in_dict_recursively, dict_merge from .file_utils import load_file, load_files from .hash import str_to_hash @@ -38,7 +37,6 @@ def minify_json(value: str) -> str: "execute_futures_dict", "execute_futures_list", "TokenCounter", - "PromptStack", "remove_null_values_in_dict_recursively", "dict_merge", "Stream", diff --git a/griptape/utils/conversation.py b/griptape/utils/conversation.py index 2d87563ae..ae05e8b99 100644 --- a/griptape/utils/conversation.py +++ b/griptape/utils/conversation.py @@ -22,8 +22,8 @@ def lines(self) -> list[str]: def prompt_stack(self) -> list[str]: lines = [] - for stack in self.memory.to_prompt_stack().inputs: - lines.append(f"{stack.role}: {stack.content}") + for stack in self.memory.to_prompt_stack().messages: + lines.append(f"{stack.role}: {stack.to_text()}") return lines diff --git a/griptape/utils/prompt_stack.py b/griptape/utils/prompt_stack.py deleted file mode 100644 index 378f9dd1e..000000000 --- a/griptape/utils/prompt_stack.py +++ /dev/null @@ -1,48 +0,0 @@ -from __future__ import annotations -from attrs import define, field - -from griptape.mixins import SerializableMixin - - -@define -class PromptStack(SerializableMixin): - GENERIC_ROLE = "generic" - USER_ROLE = "user" - ASSISTANT_ROLE = "assistant" - SYSTEM_ROLE = "system" - - @define - class Input(SerializableMixin): - content: str = field(metadata={"serializable": True}) - role: str = field(metadata={"serializable": True}) - - def is_generic(self) -> bool: - return self.role == PromptStack.GENERIC_ROLE - - def is_system(self) -> bool: - return self.role == PromptStack.SYSTEM_ROLE - - def is_user(self) -> bool: - return self.role == PromptStack.USER_ROLE - - def is_assistant(self) -> bool: - return self.role == PromptStack.ASSISTANT_ROLE - - inputs: list[Input] = field(factory=list, kw_only=True, metadata={"serializable": True}) - - def add_input(self, content: str, role: str) -> Input: - self.inputs.append(self.Input(content=content, role=role)) - - return self.inputs[-1] - - def add_generic_input(self, content: str) -> Input: - return self.add_input(content, self.GENERIC_ROLE) - - def add_system_input(self, content: str) -> Input: - return self.add_input(content, self.SYSTEM_ROLE) - - def add_user_input(self, content: str) -> Input: - return self.add_input(content, self.USER_ROLE) - - def add_assistant_input(self, content: str) -> Input: - return self.add_input(content, self.ASSISTANT_ROLE) diff --git a/tests/mocks/mock_failing_prompt_driver.py b/tests/mocks/mock_failing_prompt_driver.py index c97b25d86..0dbeb8fda 100644 --- a/tests/mocks/mock_failing_prompt_driver.py +++ b/tests/mocks/mock_failing_prompt_driver.py @@ -1,10 +1,11 @@ +from __future__ import annotations from collections.abc import Iterator from attrs import define -from griptape.utils import PromptStack -from griptape.drivers import BasePromptDriver -from griptape.tokenizers import OpenAiTokenizer, BaseTokenizer from griptape.artifacts import TextArtifact +from griptape.common import PromptStack, Message, TextMessageContent, DeltaMessage, TextDeltaMessageContent +from griptape.drivers import BasePromptDriver +from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer @define @@ -14,18 +15,25 @@ class MockFailingPromptDriver(BasePromptDriver): model: str = "test-model" tokenizer: BaseTokenizer = OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: if self.current_attempt < self.max_failures: self.current_attempt += 1 - raise Exception(f"failed attempt") + raise Exception("failed attempt") else: - return TextArtifact("success") + return Message( + content=[TextMessageContent(TextArtifact("success"))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=100, output_tokens=100), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: if self.current_attempt < self.max_failures: self.current_attempt += 1 - raise Exception(f"failed attempt") + raise Exception("failed attempt") else: - yield TextArtifact("success") + yield DeltaMessage( + content=TextDeltaMessageContent("success"), + usage=DeltaMessage.Usage(input_tokens=100, output_tokens=100), + ) diff --git a/tests/mocks/mock_prompt_driver.py b/tests/mocks/mock_prompt_driver.py index 3235f7cd5..4786b78a6 100644 --- a/tests/mocks/mock_prompt_driver.py +++ b/tests/mocks/mock_prompt_driver.py @@ -1,11 +1,15 @@ from __future__ import annotations + from collections.abc import Iterator from typing import Callable + from attrs import define, field -from griptape.utils import PromptStack + +from griptape.artifacts import TextArtifact +from griptape.common import PromptStack, Message, DeltaMessage, TextMessageContent, TextDeltaMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer -from griptape.artifacts import TextArtifact + from tests.mocks.mock_tokenizer import MockTokenizer @@ -16,12 +20,18 @@ class MockPromptDriver(BasePromptDriver): mock_input: str | Callable[[], str] = field(default="mock input", kw_only=True) mock_output: str | Callable[[PromptStack], str] = field(default="mock output", kw_only=True) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - return TextArtifact( - value=self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output - ) + def try_run(self, prompt_stack: PromptStack) -> Message: + output = self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - yield TextArtifact( - value=self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output + return Message( + content=[TextMessageContent(TextArtifact(output))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=100, output_tokens=100), ) + + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: + output = self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output + + yield DeltaMessage(content=TextDeltaMessageContent(output)) + + yield DeltaMessage(usage=DeltaMessage.Usage(input_tokens=100, output_tokens=100)) diff --git a/tests/mocks/mock_value_prompt_driver.py b/tests/mocks/mock_value_prompt_driver.py deleted file mode 100644 index 12ddeec9f..000000000 --- a/tests/mocks/mock_value_prompt_driver.py +++ /dev/null @@ -1,21 +0,0 @@ -from collections.abc import Iterator -from attrs import define, field, Factory -from griptape.drivers import BasePromptDriver -from griptape.tokenizers import OpenAiTokenizer, BaseTokenizer -from griptape.artifacts import TextArtifact -from griptape.utils.prompt_stack import PromptStack - - -@define -class MockValuePromptDriver(BasePromptDriver): - value: str = field(kw_only=True) - model: str = field(default="test-model") - tokenizer: BaseTokenizer = field( - default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)) - ) - - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - return TextArtifact(value=self.value) - - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - yield TextArtifact(value=self.value) diff --git a/tests/unit/config/test_google_structure_config.py b/tests/unit/config/test_google_structure_config.py index 72e623ff0..ad96f2a35 100644 --- a/tests/unit/config/test_google_structure_config.py +++ b/tests/unit/config/test_google_structure_config.py @@ -19,7 +19,7 @@ def test_to_dict(self, config): "temperature": 0.1, "max_tokens": None, "stream": False, - "model": "gemini-pro", + "model": "gemini-1.5-pro", "top_p": None, "top_k": None, }, diff --git a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py index ef3b0e1df..80d77d24d 100644 --- a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py @@ -81,5 +81,5 @@ def test_load(self): assert new_memory.type == "ConversationMemory" assert len(new_memory.runs) == 2 - assert new_memory.runs[0].input == "test" - assert new_memory.runs[0].output == "mock output" + assert new_memory.runs[0].input.value == "test" + assert new_memory.runs[0].output.value == "mock output" diff --git a/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py index d12d5d3d2..c794afd0e 100644 --- a/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py @@ -52,8 +52,8 @@ def test_load(self): assert new_memory.type == "ConversationMemory" assert len(new_memory.runs) == 2 - assert new_memory.runs[0].input == "test" - assert new_memory.runs[0].output == "mock output" + assert new_memory.runs[0].input.value == "test" + assert new_memory.runs[0].output.value == "mock output" assert new_memory.max_runs == 5 def test_autoload(self): @@ -71,8 +71,8 @@ def test_autoload(self): assert autoloaded_memory.type == "ConversationMemory" assert len(autoloaded_memory.runs) == 2 - assert autoloaded_memory.runs[0].input == "test" - assert autoloaded_memory.runs[0].output == "mock output" + assert autoloaded_memory.runs[0].input.value == "test" + assert autoloaded_memory.runs[0].output.value == "mock output" def __delete_file(self, file_path): try: diff --git a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py index 13f75d464..1af9d74dc 100644 --- a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py @@ -3,7 +3,7 @@ from griptape.memory.structure.base_conversation_memory import BaseConversationMemory from griptape.drivers.memory.conversation.redis_conversation_memory_driver import RedisConversationMemoryDriver -TEST_CONVERSATION = '{"type": "ConversationMemory", "runs": [{"type": "Run", "id": "729ca6be5d79433d9762eb06dfd677e2", "input": "Hi There, Hello", "output": "Hello! How can I assist you today?"}], "max_runs": 2}' +TEST_CONVERSATION = '{"type": "ConversationMemory", "runs": [{"type": "Run", "id": "729ca6be5d79433d9762eb06dfd677e2", "input": {"type": "TextArtifact", "id": "1234", "value": "Hi There, Hello"}, "output": {"type": "TextArtifact", "id": "123", "value": "Hello! How can I assist you today?"}}], "max_runs": 2}' CONVERSATION_ID = "117151897f344ff684b553d0655d8f39" INDEX = "griptape_conversation" HOST = "127.0.0.1" diff --git a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py index 8aa345595..3cd165140 100644 --- a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py @@ -1,6 +1,7 @@ import pytest -from griptape.utils import PromptStack +from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.common import PromptStack from griptape.drivers import AmazonBedrockPromptDriver @@ -9,7 +10,10 @@ class TestAmazonBedrockPromptDriver: def mock_converse(self, mocker): mock_converse = mocker.patch("boto3.Session").return_value.client.return_value.converse - mock_converse.return_value = {"output": {"message": {"content": [{"text": "model-output"}]}}} + mock_converse.return_value = { + "output": {"message": {"content": [{"text": "model-output"}]}}, + "usage": {"inputTokens": 5, "outputTokens": 10}, + } return mock_converse @@ -17,26 +21,33 @@ def mock_converse(self, mocker): def mock_converse_stream(self, mocker): mock_converse_stream = mocker.patch("boto3.Session").return_value.client.return_value.converse_stream - mock_converse_stream.return_value = {"stream": [{"contentBlockDelta": {"delta": {"text": "model-output"}}}]} + mock_converse_stream.return_value = { + "stream": [ + {"contentBlockDelta": {"contentBlockIndex": 0, "delta": {"text": "model-output"}}}, + {"metadata": {"usage": {"inputTokens": 5, "outputTokens": 10}}}, + ] + } return mock_converse_stream - @pytest.fixture - def prompt_stack(self): + @pytest.fixture(params=[True, False]) + def prompt_stack(self, request): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + if request.param: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") return prompt_stack @pytest.fixture def messages(self): return [ - {"role": "user", "content": [{"text": "generic-input"}]}, - {"role": "system", "content": [{"text": "system-input"}]}, {"role": "user", "content": [{"text": "user-input"}]}, + {"role": "user", "content": [{"text": "user-input"}]}, + {"role": "user", "content": [{"image": {"format": "png", "source": {"bytes": b"image-data"}}}]}, {"role": "assistant", "content": [{"text": "assistant-input"}]}, ] @@ -50,34 +61,34 @@ def test_try_run(self, mock_converse, prompt_stack, messages): # Then mock_converse.assert_called_once_with( modelId=driver.model, - messages=[ - {"role": "user", "content": [{"text": "generic-input"}]}, - {"role": "user", "content": [{"text": "user-input"}]}, - {"role": "assistant", "content": [{"text": "assistant-input"}]}, - ], - system=[{"text": "system-input"}], + messages=messages, + **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), inferenceConfig={"temperature": driver.temperature}, additionalModelRequestFields={}, ) assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 def test_try_stream_run(self, mock_converse_stream, prompt_stack, messages): # Given driver = AmazonBedrockPromptDriver(model="ai21.j2", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_converse_stream.assert_called_once_with( modelId=driver.model, - messages=[ - {"role": "user", "content": [{"text": "generic-input"}]}, - {"role": "user", "content": [{"text": "user-input"}]}, - {"role": "assistant", "content": [{"text": "assistant-input"}]}, - ], - system=[{"text": "system-input"}], + messages=messages, + **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), inferenceConfig={"temperature": driver.temperature}, additionalModelRequestFields={}, ) - assert text_artifact.value == "model-output" + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py index 4ae8fe944..a75fc6ed0 100644 --- a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py @@ -2,7 +2,7 @@ from botocore.response import StreamingBody from griptape.tokenizers import HuggingFaceTokenizer from griptape.drivers.prompt.amazon_sagemaker_jumpstart_prompt_driver import AmazonSageMakerJumpstartPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack from io import BytesIO import json import pytest @@ -18,7 +18,9 @@ class TestAmazonSageMakerJumpstartPromptDriver: @pytest.fixture(autouse=True) def tokenizer(self, mocker): from_pretrained = mocker.patch("transformers.AutoTokenizer").from_pretrained - from_pretrained.return_value.apply_chat_template.return_value = "foo\n\nUser: bar" + from_pretrained.return_value.decode.return_value = "foo\n\nUser: bar" + from_pretrained.return_value.apply_chat_template.return_value = [1, 2, 3] + from_pretrained.return_value.encode.return_value = [1, 2, 3] from_pretrained.return_value.model_max_length = 8000 from_pretrained.return_value.eos_token_id = 1 @@ -35,7 +37,7 @@ def test_try_run(self, mock_client): # Given driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") + prompt_stack.add_user_message("prompt-stack") # When response_body = [{"generated_text": "foobar"}] @@ -64,6 +66,8 @@ def test_try_run(self, mock_client): ) assert text_artifact.value == "foobar" + assert text_artifact.usage.input_tokens == 3 + assert text_artifact.usage.output_tokens == 3 # When response_body = {"generated_text": "foobar"} @@ -97,7 +101,7 @@ def test_try_stream(self, mock_client): # Given driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") + prompt_stack.add_user_message("prompt-stack") # When with pytest.raises(NotImplementedError) as e: @@ -122,7 +126,7 @@ def test_try_run_throws_on_empty_response(self, mock_client): driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") mock_client.invoke_endpoint.return_value = {"Body": to_streaming_body([])} prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") + prompt_stack.add_user_message("prompt-stack") # When with pytest.raises(Exception) as e: diff --git a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py index 22178bbf3..858c05ee6 100644 --- a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py @@ -1,5 +1,6 @@ from griptape.drivers import AnthropicPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.artifacts import TextArtifact, ImageArtifact, ListArtifact from unittest.mock import Mock import pytest @@ -8,21 +9,36 @@ class TestAnthropicPromptDriver: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("anthropic.Anthropic") - mock_content = Mock() - mock_content.text = "model-output" - mock_client.return_value.messages.create.return_value.content = [mock_content] - mock_client.return_value.count_tokens.return_value = 5 + + mock_client.return_value = Mock( + messages=Mock( + create=Mock( + return_value=Mock( + usage=Mock(input_tokens=5, output_tokens=10), content=[Mock(type="text", text="model-output")] + ) + ) + ) + ) return mock_client @pytest.fixture def mock_stream_client(self, mocker): mock_stream_client = mocker.patch("anthropic.Anthropic") - mock_chunk = Mock() - mock_chunk.type = "content_block_delta" - mock_chunk.delta.text = "model-output" - mock_stream_client.return_value.messages.create.return_value = iter([mock_chunk]) - mock_stream_client.return_value.count_tokens.return_value = 5 + + mock_stream_client.return_value = Mock( + messages=Mock( + create=Mock( + return_value=iter( + [ + Mock(type="message_start", message=Mock(usage=Mock(input_tokens=5))), + Mock(type="content_block_delta", delta=Mock(type="text_delta", text="model-output")), + Mock(type="message_delta", usage=Mock(output_tokens=10)), + ] + ) + ) + ) + ) return mock_stream_client @@ -45,20 +61,30 @@ def test_init(self, model): def test_try_run(self, mock_client, model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") if system_enabled: - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") driver = AnthropicPromptDriver(model=model, api_key="api-key") expected_messages = [ - {"role": "user", "content": "generic-input"}, {"role": "user", "content": "user-input"}, + {"role": "user", "content": "user-input"}, + { + "content": [ + { + "source": {"data": "aW1hZ2UtZGF0YQ==", "media_type": "image/png", "type": "base64"}, + "type": "image", + } + ], + "role": "user", + }, {"role": "assistant", "content": "assistant-input"}, ] # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_client.return_value.messages.create.assert_called_once_with( @@ -71,7 +97,9 @@ def test_try_run(self, mock_client, model, system_enabled): top_k=250, **{"system": "system-input"} if system_enabled else {}, ) - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 5 + assert message.usage.output_tokens == 10 @pytest.mark.parametrize( "model", @@ -88,20 +116,34 @@ def test_try_run(self, mock_client, model, system_enabled): def test_try_stream_run(self, mock_stream_client, model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") if system_enabled: - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") expected_messages = [ - {"role": "user", "content": "generic-input"}, {"role": "user", "content": "user-input"}, + { + "content": [ + {"type": "text", "text": "user-input"}, + { + "source": {"data": "aW1hZ2UtZGF0YQ==", "media_type": "image/png", "type": "base64"}, + "type": "image", + }, + ], + "role": "user", + }, {"role": "assistant", "content": "assistant-input"}, ] driver = AnthropicPromptDriver(model=model, api_key="api-key", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_stream_client.return_value.messages.create.assert_called_once_with( @@ -115,7 +157,13 @@ def test_try_stream_run(self, mock_stream_client, model, system_enabled): top_k=250, **{"system": "system-input"} if system_enabled else {}, ) - assert text_artifact.value == "model-output" + assert event.usage.input_tokens == 5 + + event = next(stream) + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.output_tokens == 10 def test_try_run_throws_when_prompt_stack_is_string(self): # Given @@ -127,4 +175,4 @@ def test_try_run_throws_when_prompt_stack_is_string(self): driver.try_run(prompt_stack) # pyright: ignore # Then - assert e.value.args[0] == "'str' object has no attribute 'inputs'" + assert e.value.args[0] == "'str' object has no attribute 'messages'" diff --git a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py index f6bd12d80..92544a74e 100644 --- a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py @@ -8,20 +8,22 @@ class TestAzureOpenAiChatPromptDriver(TestOpenAiChatPromptDriverFixtureMixin): @pytest.fixture def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create - mock_choice = Mock() - mock_choice.message.content = "model-output" - mock_chat_create.return_value.headers = {} - mock_chat_create.return_value.choices = [mock_choice] + mock_chat_create.return_value = Mock( + headers={}, + choices=[Mock(message=Mock(content="model-output"))], + usage=Mock(prompt_tokens=5, completion_tokens=10), + ) return mock_chat_create @pytest.fixture def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create - mock_chunk = Mock() - mock_choice = Mock() - mock_choice.delta.content = "model-output" - mock_chunk.choices = [mock_choice] - mock_chat_create.return_value = iter([mock_chunk]) + mock_chat_create.return_value = iter( + [ + Mock(choices=[Mock(delta=Mock(content="model-output"))], usage=None), + Mock(choices=None, usage=Mock(prompt_tokens=5, completion_tokens=10)), + ] + ) return mock_chat_create def test_init(self): @@ -37,13 +39,11 @@ def test_try_run(self, mock_chat_completion_create, prompt_stack, messages): # Then mock_chat_completion_create.assert_called_once_with( - model=driver.model, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - messages=messages, + model=driver.model, temperature=driver.temperature, user=driver.user, messages=messages ) assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages): # Given @@ -52,15 +52,21 @@ def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, ) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_chat_completion_stream_create.assert_called_once_with( model=driver.model, temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, user=driver.user, stream=True, messages=messages, + stream_options={"include_usage": True}, ) - assert text_artifact.value == "model-output" + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_base_prompt_driver.py b/tests/unit/drivers/prompt/test_base_prompt_driver.py index 0743402aa..6eb000e1f 100644 --- a/tests/unit/drivers/prompt/test_base_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_base_prompt_driver.py @@ -1,5 +1,6 @@ +from griptape.common.prompt_stack.messages.message import Message from griptape.events import FinishPromptEvent, StartPromptEvent -from griptape.utils import PromptStack +from griptape.common import PromptStack from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_failing_prompt_driver import MockFailingPromptDriver from griptape.artifacts import ErrorArtifact, TextArtifact @@ -37,7 +38,13 @@ def test_run_via_pipeline_publishes_events(self, mocker): assert instance_count(events, FinishPromptEvent) == 1 def test_run(self): - assert isinstance(MockPromptDriver().run(PromptStack(inputs=[])), TextArtifact) + assert isinstance(MockPromptDriver().run(PromptStack(messages=[])), Message) + + def test_run_with_stream(self): + pipeline = Pipeline() + result = MockPromptDriver(stream=True, structure=pipeline).run(PromptStack(messages=[])) + assert isinstance(result, Message) + assert result.value == "mock output" def instance_count(instances, clazz): diff --git a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py index 6e5063b26..d65775e8b 100644 --- a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py @@ -1,22 +1,30 @@ -from griptape.drivers import CoherePromptDriver -from griptape.utils import PromptStack from unittest.mock import Mock + import pytest +from griptape.common import PromptStack +from griptape.drivers import CoherePromptDriver + class TestCoherePromptDriver: @pytest.fixture def mock_client(self, mocker): - mock_client = mocker.patch("cohere.Client") - mock_client.return_value.chat.return_value = Mock(text="model-output") + mock_client = mocker.patch("cohere.Client").return_value + mock_client.chat.return_value = Mock( + text="model-output", meta=Mock(tokens=Mock(input_tokens=5, output_tokens=10)) + ) return mock_client @pytest.fixture def mock_stream_client(self, mocker): - mock_client = mocker.patch("cohere.Client") - mock_chunk = Mock(text="model-output", event_type="text-generation") - mock_client.return_value.chat_stream.return_value = iter([mock_chunk]) + mock_client = mocker.patch("cohere.Client").return_value + mock_client.chat_stream.return_value = iter( + [ + Mock(text="model-output", event_type="text-generation"), + Mock(response=Mock(meta=Mock(tokens=Mock(input_tokens=5, output_tokens=10))), event_type="stream-end"), + ] + ) return mock_client @@ -24,67 +32,70 @@ def mock_stream_client(self, mocker): def mock_tokenizer(self, mocker): return mocker.patch("griptape.tokenizers.CohereTokenizer").return_value - @pytest.fixture - def prompt_stack(self): + @pytest.fixture(params=[True, False]) + def prompt_stack(self, request): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + if request.param: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") return prompt_stack def test_init(self): assert CoherePromptDriver(model="command", api_key="foobar") - def test_try_run(self, mock_client, prompt_stack): # pyright: ignore + def test_try_run(self, mock_client, prompt_stack): # Given driver = CoherePromptDriver(model="command", api_key="api-key") # When text_artifact = driver.try_run(prompt_stack) - print(f"Called methods: {mock_client}") # Then - expected_message = "assistant-input" - expected_history = [ - {"role": "ASSISTANT", "text": "generic-input"}, - {"role": "SYSTEM", "text": "system-input"}, - {"role": "USER", "text": "user-input"}, - ] - mock_client.return_value.chat.assert_called_once_with( - message=expected_message, - temperature=driver.temperature, - stop_sequences=driver.tokenizer.stop_sequences, - max_tokens=driver.max_tokens, - chat_history=expected_history, + mock_client.chat.assert_called_once_with( + chat_history=[ + {"content": [{"text": "user-input"}], "role": "USER"}, + {"content": [{"text": "assistant-input"}], "role": "CHATBOT"}, + {"content": [{"text": "user-input"}], "role": "USER"}, + ], + max_tokens=None, + message="assistant-input", + **({"preamble": "system-input"} if prompt_stack.system_messages else {}), + stop_sequences=[], + temperature=0.1, ) - assert text_artifact.value == "model-output" - - def test_try_run_no_history(self, mock_client, prompt_stack): - # Given - prompt_stack_no_history = PromptStack() - prompt_stack_no_history.add_user_input("user-input") - driver = CoherePromptDriver(model="command", api_key="api-key") - - # When - text_artifact = driver.try_run(prompt_stack_no_history) - # Then - expected_message = "user-input" - mock_client.return_value.chat.assert_called_once_with( - message=expected_message, - temperature=driver.temperature, - stop_sequences=driver.tokenizer.stop_sequences, - max_tokens=driver.max_tokens, - ) assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 def test_try_stream_run(self, mock_stream_client, prompt_stack): # pyright: ignore # Given driver = CoherePromptDriver(model="command", api_key="api-key", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then - assert text_artifact.value == "model-output" + + mock_stream_client.chat_stream.assert_called_once_with( + chat_history=[ + {"content": [{"text": "user-input"}], "role": "USER"}, + {"content": [{"text": "assistant-input"}], "role": "CHATBOT"}, + {"content": [{"text": "user-input"}], "role": "USER"}, + ], + max_tokens=None, + message="assistant-input", + **({"preamble": "system-input"} if prompt_stack.system_messages else {}), + stop_sequences=[], + temperature=0.1, + ) + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_google_prompt_driver.py b/tests/unit/drivers/prompt/test_google_prompt_driver.py index f655d3e51..6a25ec3d3 100644 --- a/tests/unit/drivers/prompt/test_google_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_google_prompt_driver.py @@ -1,6 +1,7 @@ from google.generativeai.types import GenerationConfig +from griptape.artifacts import TextArtifact, ImageArtifact from griptape.drivers import GooglePromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack from unittest.mock import Mock import pytest @@ -9,14 +10,21 @@ class TestGooglePromptDriver: @pytest.fixture def mock_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") - mock_generative_model.return_value.generate_content.return_value = Mock(text="model-output") + mock_generative_model.return_value.generate_content.return_value = Mock( + text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=10) + ) return mock_generative_model @pytest.fixture def mock_stream_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") - mock_generative_model.return_value.generate_content.return_value = iter([Mock(text="model-output")]) + mock_generative_model.return_value.generate_content.return_value = iter( + [ + Mock(text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5)), + Mock(text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5)), + ] + ) return mock_generative_model @@ -24,75 +32,77 @@ def test_init(self): driver = GooglePromptDriver(model="gemini-pro", api_key="1234") assert driver - def test_try_run(self, mock_generative_model): + @pytest.mark.parametrize("system_enabled", [True, False]) + def test_try_run(self, mock_generative_model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_generic_input("generic-input") + if system_enabled: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", top_p=0.5, top_k=50) # When text_artifact = driver.try_run(prompt_stack) # Then + messages = [ + *( + [{"parts": ["system-input", "user-input"], "role": "user"}] + if system_enabled + else [{"parts": ["user-input"], "role": "user"}] + ), + {"parts": ["user-input"], "role": "user"}, + {"parts": [{"data": b"image-data", "mime_type": "image/png"}], "role": "user"}, + {"parts": ["assistant-input"], "role": "model"}, + ] mock_generative_model.return_value.generate_content.assert_called_once_with( - [ - {"parts": ["system-input", "user-input"], "role": "user"}, - {"parts": ["assistant-input"], "role": "model"}, - {"parts": ["generic-input"], "role": "user"}, - ], + messages, generation_config=GenerationConfig( max_output_tokens=None, temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[] ), ) assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 - def test_try_stream(self, mock_stream_generative_model): + @pytest.mark.parametrize("system_enabled", [True, False]) + def test_try_stream(self, mock_stream_generative_model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_generic_input("generic-input") + if system_enabled: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", stream=True, top_p=0.5, top_k=50) # When - text_artifact_stream = driver.try_stream(prompt_stack) + stream = driver.try_stream(prompt_stack) # Then - text_artifact = next(text_artifact_stream) + event = next(stream) + messages = [ + *( + [{"parts": ["system-input", "user-input"], "role": "user"}] + if system_enabled + else [{"parts": ["user-input"], "role": "user"}] + ), + {"parts": ["user-input"], "role": "user"}, + {"parts": [{"data": b"image-data", "mime_type": "image/png"}], "role": "user"}, + {"parts": ["assistant-input"], "role": "model"}, + ] mock_stream_generative_model.return_value.generate_content.assert_called_once_with( - [ - {"parts": ["system-input", "user-input"], "role": "user"}, - {"parts": ["assistant-input"], "role": "model"}, - {"parts": ["generic-input"], "role": "user"}, - ], + messages, stream=True, generation_config=GenerationConfig(temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[]), ) - assert text_artifact.value == "model-output" - - def test_prompt_stack_to_model_input(self): - # Given - driver = GooglePromptDriver(model="gemini-pro", api_key="1234") - prompt_stack = PromptStack() - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_user_input("user-input") + assert event.content.text == "model-output" + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 5 - # When - model_input = driver._prompt_stack_to_model_input(prompt_stack) - - # Then - assert model_input == [ - {"role": "user", "parts": ["system-input", "user-input"]}, - {"role": "model", "parts": ["assistant-input"]}, - {"role": "user", "parts": ["generic-input"]}, - {"role": "model", "parts": ["assistant-input"]}, - {"role": "user", "parts": ["user-input"]}, - ] + event = next(stream) + assert event.usage.output_tokens == 5 diff --git a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py index 15bbb4ead..4618e1de3 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py @@ -1,5 +1,5 @@ from griptape.drivers import HuggingFaceHubPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack import pytest @@ -7,6 +7,7 @@ class TestHuggingFaceHubPromptDriver: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("huggingface_hub.InferenceClient").return_value + mock_client.text_generation.return_value = "model-output" return mock_client @@ -14,6 +15,8 @@ def mock_client(self, mocker): def tokenizer(self, mocker): from_pretrained = tokenizer = mocker.patch("transformers.AutoTokenizer").from_pretrained from_pretrained.return_value.apply_chat_template.return_value = [1, 2, 3] + from_pretrained.return_value.decode.return_value = "foo\n\nUser: bar" + from_pretrained.return_value.encode.return_value = [1, 2, 3] return tokenizer @@ -27,10 +30,9 @@ def mock_client_stream(self, mocker): @pytest.fixture def prompt_stack(self): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") return prompt_stack @pytest.fixture(autouse=True) @@ -47,17 +49,24 @@ def test_try_run(self, prompt_stack, mock_client): driver = HuggingFaceHubPromptDriver(api_token="api-token", model="repo-id") # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 3 + assert message.usage.output_tokens == 3 def test_try_stream(self, prompt_stack, mock_client_stream): # Given driver = HuggingFaceHubPromptDriver(api_token="api-token", model="repo-id", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then - assert text_artifact.value == "model-output" + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 3 + assert event.usage.output_tokens == 3 diff --git a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py index b2746ca58..a63d697fb 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py @@ -1,5 +1,5 @@ from griptape.drivers import HuggingFacePipelinePromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack import pytest @@ -22,15 +22,15 @@ def mock_autotokenizer(self, mocker): mock_autotokenizer.model_max_length = 42 mock_autotokenizer.apply_chat_template.return_value = [1, 2, 3] mock_autotokenizer.decode.return_value = "model-output" + mock_autotokenizer.encode.return_value = [1, 2, 3] return mock_autotokenizer @pytest.fixture def prompt_stack(self): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") return prompt_stack def test_init(self): @@ -41,10 +41,12 @@ def test_try_run(self, prompt_stack): driver = HuggingFacePipelinePromptDriver(model="foo", max_tokens=42) # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 3 + assert message.usage.output_tokens == 3 def test_try_stream(self, prompt_stack): # Given diff --git a/tests/unit/drivers/prompt/test_ollama_prompt_driver.py b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py index d42a8b45d..a247a77ab 100644 --- a/tests/unit/drivers/prompt/test_ollama_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py @@ -1,5 +1,7 @@ +from griptape.common.prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent from griptape.drivers import OllamaPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact import pytest @@ -25,20 +27,24 @@ def test_init(self): def test_try_run(self, mock_client): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") driver = OllamaPromptDriver(model="llama") expected_messages = [ - {"role": "generic", "content": "generic-input"}, {"role": "system", "content": "system-input"}, {"role": "user", "content": "user-input"}, + {"role": "user", "content": "user-input", "images": ["aW1hZ2UtZGF0YQ=="]}, {"role": "assistant", "content": "assistant-input"}, ] # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_client.return_value.chat.assert_called_once_with( @@ -46,7 +52,9 @@ def test_try_run(self, mock_client): model=driver.model, options={"temperature": driver.temperature, "stop": [], "num_predict": driver.max_tokens}, ) - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens is None + assert message.usage.output_tokens is None def test_try_run_bad_response(self, mock_client): # Given @@ -61,14 +69,18 @@ def test_try_run_bad_response(self, mock_client): def test_try_stream_run(self, mock_stream_client): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") expected_messages = [ - {"role": "generic", "content": "generic-input"}, {"role": "system", "content": "system-input"}, {"role": "user", "content": "user-input"}, + {"role": "user", "content": "user-input", "images": ["aW1hZ2UtZGF0YQ=="]}, {"role": "assistant", "content": "assistant-input"}, ] driver = OllamaPromptDriver(model="llama", stream=True) @@ -83,7 +95,8 @@ def test_try_stream_run(self, mock_stream_client): options={"temperature": driver.temperature, "stop": [], "num_predict": driver.max_tokens}, stream=True, ) - assert text_artifact.value == "model-output" + if isinstance(text_artifact, TextDeltaMessageContent): + assert text_artifact.text == "model-output" def test_try_stream_bad_response(self, mock_stream_client): # Given diff --git a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py index a2900d4d3..5c217ed06 100644 --- a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py @@ -1,8 +1,10 @@ +from griptape.artifacts import ImageArtifact, ListArtifact +from griptape.artifacts import TextArtifact from griptape.drivers import OpenAiChatPromptDriver -from griptape.tokenizers.huggingface_tokenizer import HuggingFaceTokenizer -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.tokenizers import OpenAiTokenizer from unittest.mock import Mock +from tests.mocks.mock_tokenizer import MockTokenizer import pytest @@ -10,37 +12,51 @@ class TestOpenAiChatPromptDriverFixtureMixin: @pytest.fixture def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create - mock_choice = Mock() - mock_choice.message.content = "model-output" - mock_chat_create.return_value.headers = {} - mock_chat_create.return_value.choices = [mock_choice] + mock_chat_create.return_value = Mock( + headers={}, + choices=[Mock(message=Mock(content="model-output"))], + usage=Mock(prompt_tokens=5, completion_tokens=10), + ) + return mock_chat_create @pytest.fixture def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create - mock_chunk = Mock() - mock_choice = Mock() - mock_choice.delta.content = "model-output" - mock_chunk.choices = [mock_choice] - mock_chat_create.return_value = iter([mock_chunk]) + mock_chat_create.return_value = iter( + [ + Mock(choices=[Mock(delta=Mock(content="model-output"))], usage=None), + Mock(choices=None, usage=Mock(prompt_tokens=5, completion_tokens=10)), + Mock(choices=[Mock(delta=Mock(content=None))], usage=None), + ] + ) return mock_chat_create @pytest.fixture def prompt_stack(self): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") return prompt_stack @pytest.fixture def messages(self): return [ - {"role": "user", "content": "generic-input"}, {"role": "system", "content": "system-input"}, {"role": "user", "content": "user-input"}, + { + "role": "user", + "content": [ + {"type": "text", "text": "user-input"}, + {"type": "image_url", "image_url": {"url": "data:image/png;base64,aW1hZ2UtZGF0YQ=="}}, + ], + }, {"role": "assistant", "content": "assistant-input"}, ] @@ -87,18 +103,13 @@ def test_try_run(self, mock_chat_completion_create, prompt_stack, messages): driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) # When - text_artifact = driver.try_run(prompt_stack) + event = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( - model=driver.model, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - messages=messages, - seed=driver.seed, + model=driver.model, temperature=driver.temperature, user=driver.user, messages=messages, seed=driver.seed ) - assert text_artifact.value == "model-output" + assert event.value == "model-output" def test_try_run_response_format(self, mock_chat_completion_create, prompt_stack, messages): # Given @@ -107,57 +118,65 @@ def test_try_run_response_format(self, mock_chat_completion_create, prompt_stack ) # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( model=driver.model, temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, user=driver.user, messages=[*messages, {"role": "system", "content": "Provide your response as a valid JSON object."}], seed=driver.seed, response_format={"type": "json_object"}, ) - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 5 + assert message.usage.output_tokens == 10 def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_chat_completion_stream_create.assert_called_once_with( model=driver.model, temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, user=driver.user, stream=True, messages=messages, seed=driver.seed, + stream_options={"include_usage": True}, ) - assert text_artifact.value == "model-output" + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 + event = next(stream) + assert event.content.text == "" def test_try_run_with_max_tokens(self, mock_chat_completion_create, prompt_stack, messages): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, max_tokens=1) # When - text_artifact = driver.try_run(prompt_stack) + event = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( model=driver.model, temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, user=driver.user, messages=messages, max_tokens=1, seed=driver.seed, ) - assert text_artifact.value == "model-output" + assert event.value == "model-output" def test_try_run_throws_when_prompt_stack_is_string(self): # Given @@ -168,30 +187,29 @@ def test_try_run_throws_when_prompt_stack_is_string(self): driver.try_run("prompt-stack") # pyright: ignore # Then - assert e.value.args[0] == "'str' object has no attribute 'inputs'" + assert e.value.args[0] == "'str' object has no attribute 'messages'" - @pytest.mark.parametrize("choices", [[], [1, 2]]) - def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_chat_completion_create, prompt_stack): + def test_try_run_throws_when_multiple_choices_returned(self, mock_chat_completion_create, prompt_stack): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, api_key="api-key") - mock_chat_completion_create.return_value.choices = [choices] + mock_chat_completion_create.return_value.choices = [Mock(message=Mock(content="model-output"))] * 10 # When with pytest.raises(Exception) as e: driver.try_run(prompt_stack) # Then - e.value.args[0] == "Completion with more than one choice is not supported yet." + assert e.value.args[0] == "Completion with more than one choice is not supported yet." def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messages): driver = OpenAiChatPromptDriver( model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, - tokenizer=HuggingFaceTokenizer(model="gpt2", max_output_tokens=1000), + tokenizer=MockTokenizer(model="mock-model", stop_sequences=["mock-stop"]), max_tokens=1, ) # When - text_artifact = driver.try_run(prompt_stack) + event = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( @@ -199,13 +217,8 @@ def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messa temperature=driver.temperature, stop=driver.tokenizer.stop_sequences, user=driver.user, - messages=[ - {"role": "user", "content": "generic-input"}, - {"role": "system", "content": "system-input"}, - {"role": "user", "content": "user-input"}, - {"role": "assistant", "content": "assistant-input"}, - ], + messages=messages, seed=driver.seed, max_tokens=1, ) - assert text_artifact.value == "model-output" + assert event.value == "model-output" diff --git a/tests/unit/engines/summary/test_prompt_summary_engine.py b/tests/unit/engines/summary/test_prompt_summary_engine.py index 59b36f48e..34c6e3563 100644 --- a/tests/unit/engines/summary/test_prompt_summary_engine.py +++ b/tests/unit/engines/summary/test_prompt_summary_engine.py @@ -1,7 +1,7 @@ import pytest from griptape.artifacts import TextArtifact, ListArtifact from griptape.engines import PromptSummaryEngine -from griptape.utils import PromptStack +from griptape.common import PromptStack from tests.mocks.mock_prompt_driver import MockPromptDriver import os @@ -28,7 +28,7 @@ def test_max_token_multiplier_invalid(self, engine): def test_chunked_summary(self, engine): def smaller_input(prompt_stack: PromptStack): - return prompt_stack.inputs[0].content[: (len(prompt_stack.inputs[0].content) // 2)] + return prompt_stack.messages[0].content[: (len(prompt_stack.messages[0].content) // 2)] engine = PromptSummaryEngine(prompt_driver=MockPromptDriver(mock_output="smaller_input")) diff --git a/tests/unit/events/test_base_event.py b/tests/unit/events/test_base_event.py index 7656b6b0d..595c90f1f 100644 --- a/tests/unit/events/test_base_event.py +++ b/tests/unit/events/test_base_event.py @@ -29,30 +29,48 @@ def test_to_dict(self): def test_start_prompt_event_from_dict(self): dict_value = { "type": "StartPromptEvent", - "timestamp": 123.0, - "token_count": 10, - "prompt_stack": {"inputs": [{"content": "foo", "role": "user"}, {"content": "bar", "role": "system"}]}, - "prompt": "foo bar", + "id": "917298d4bf894b0a824a8fdb26717a0c", + "timestamp": 123, "model": "foo bar", + "prompt_stack": { + "type": "PromptStack", + "messages": [ + { + "type": "Message", + "role": "user", + "content": [ + {"type": "TextMessageContent", "artifact": {"type": "TextArtifact", "value": "foo"}} + ], + "usage": {"type": "Usage", "input_tokens": None, "output_tokens": None}, + }, + { + "type": "Message", + "role": "system", + "content": [ + {"type": "TextMessageContent", "artifact": {"type": "TextArtifact", "value": "bar"}} + ], + "usage": {"type": "Usage", "input_tokens": None, "output_tokens": None}, + }, + ], + }, } event = BaseEvent.from_dict(dict_value) assert isinstance(event, StartPromptEvent) assert event.timestamp == 123 - assert event.token_count == 10 - assert event.prompt_stack.inputs[0].content == "foo" - assert event.prompt_stack.inputs[0].role == "user" - assert event.prompt_stack.inputs[1].content == "bar" - assert event.prompt_stack.inputs[1].role == "system" - assert event.prompt == "foo bar" + assert event.prompt_stack.messages[0].content[0].artifact.value == "foo" + assert event.prompt_stack.messages[0].role == "user" + assert event.prompt_stack.messages[1].content[0].artifact.value == "bar" + assert event.prompt_stack.messages[1].role == "system" assert event.model == "foo bar" def test_finish_prompt_event_from_dict(self): dict_value = { "type": "FinishPromptEvent", "timestamp": 123.0, - "token_count": 10, + "input_token_count": 10, + "output_token_count": 12, "result": "foo bar", "model": "foo bar", } @@ -61,7 +79,8 @@ def test_finish_prompt_event_from_dict(self): assert isinstance(event, FinishPromptEvent) assert event.timestamp == 123 - assert event.token_count == 10 + assert event.input_token_count == 10 + assert event.output_token_count == 12 assert event.result == "foo bar" assert event.model == "foo bar" diff --git a/tests/unit/events/test_finish_prompt_event.py b/tests/unit/events/test_finish_prompt_event.py index b788c67f9..7443fce0c 100644 --- a/tests/unit/events/test_finish_prompt_event.py +++ b/tests/unit/events/test_finish_prompt_event.py @@ -5,12 +5,13 @@ class TestFinishPromptEvent: @pytest.fixture def finish_prompt_event(self): - return FinishPromptEvent(token_count=123, result="foo bar", model="foo bar") + return FinishPromptEvent(input_token_count=321, output_token_count=123, result="foo bar", model="foo bar") def test_to_dict(self, finish_prompt_event): assert "timestamp" in finish_prompt_event.to_dict() - assert finish_prompt_event.to_dict()["token_count"] == 123 + assert finish_prompt_event.to_dict()["input_token_count"] == 321 + assert finish_prompt_event.to_dict()["output_token_count"] == 123 assert finish_prompt_event.to_dict()["result"] == "foo bar" assert finish_prompt_event.to_dict()["model"] == "foo bar" diff --git a/tests/unit/events/test_start_prompt_event.py b/tests/unit/events/test_start_prompt_event.py index a80f8cdfc..4ef08ec5c 100644 --- a/tests/unit/events/test_start_prompt_event.py +++ b/tests/unit/events/test_start_prompt_event.py @@ -1,24 +1,22 @@ import pytest from griptape.events import StartPromptEvent -from griptape.utils import PromptStack +from griptape.common import PromptStack class TestStartPromptEvent: @pytest.fixture def start_prompt_event(self): prompt_stack = PromptStack() - prompt_stack.add_user_input("foo") - prompt_stack.add_system_input("bar") - return StartPromptEvent(token_count=123, prompt_stack=prompt_stack, prompt="foo bar", model="foo bar") + prompt_stack.add_user_message("foo") + prompt_stack.add_system_message("bar") + return StartPromptEvent(prompt_stack=prompt_stack, model="foo bar") def test_to_dict(self, start_prompt_event): assert "timestamp" in start_prompt_event.to_dict() - assert start_prompt_event.to_dict()["token_count"] == 123 - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][0]["content"] == "foo" - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][0]["role"] == "user" - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][1]["content"] == "bar" - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][1]["role"] == "system" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][0]["content"][0]["artifact"]["value"] == "foo" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][0]["role"] == "user" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][1]["content"][0]["artifact"]["value"] == "bar" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][1]["role"] == "system" - assert start_prompt_event.to_dict()["prompt"] == "foo bar" assert start_prompt_event.to_dict()["model"] == "foo bar" diff --git a/tests/unit/memory/structure/test_conversation_memory.py b/tests/unit/memory/structure/test_conversation_memory.py index 298e5ac3f..613d4b1fe 100644 --- a/tests/unit/memory/structure/test_conversation_memory.py +++ b/tests/unit/memory/structure/test_conversation_memory.py @@ -1,17 +1,18 @@ import json from griptape.structures import Agent -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.memory.structure import ConversationMemory, Run, BaseConversationMemory from griptape.structures import Pipeline from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tokenizer import MockTokenizer from griptape.tasks import PromptTask +from griptape.artifacts import TextArtifact class TestConversationMemory: def test_add_run(self): memory = ConversationMemory() - run = Run(input="test", output="test") + run = Run(input=TextArtifact("foo"), output=TextArtifact("bar")) memory.add_run(run) @@ -19,42 +20,42 @@ def test_add_run(self): def test_to_json(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert json.loads(memory.to_json())["type"] == "ConversationMemory" - assert json.loads(memory.to_json())["runs"][0]["input"] == "foo" + assert json.loads(memory.to_json())["runs"][0]["input"]["value"] == "foo" def test_to_dict(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert memory.to_dict()["type"] == "ConversationMemory" - assert memory.to_dict()["runs"][0]["input"] == "foo" + assert memory.to_dict()["runs"][0]["input"]["value"] == "foo" def test_to_prompt_stack(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) prompt_stack = memory.to_prompt_stack() - assert prompt_stack.inputs[0].content == "foo" - assert prompt_stack.inputs[1].content == "bar" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + assert prompt_stack.messages[1].content[0].artifact.value == "bar" def test_from_dict(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(BaseConversationMemory.from_dict(memory_dict), ConversationMemory) - assert BaseConversationMemory.from_dict(memory_dict).runs[0].input == "foo" + assert BaseConversationMemory.from_dict(memory_dict).runs[0].input.value == "foo" def test_from_json(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(memory.from_dict(memory_dict), ConversationMemory) - assert memory.from_dict(memory_dict).runs[0].input == "foo" + assert memory.from_dict(memory_dict).runs[0].input.value == "foo" def test_buffering(self): memory = ConversationMemory(max_runs=2) @@ -70,28 +71,28 @@ def test_buffering(self): pipeline.run("run5") assert len(pipeline.conversation_memory.runs) == 2 - assert pipeline.conversation_memory.runs[0].input == "run4" - assert pipeline.conversation_memory.runs[1].input == "run5" + assert pipeline.conversation_memory.runs[0].input.value == "run4" + assert pipeline.conversation_memory.runs[1].input.value == "run5" def test_add_to_prompt_stack_autopruing_disabled(self): agent = Agent(prompt_driver=MockPromptDriver()) memory = ConversationMemory( autoprune=False, runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_user_message(TextArtifact("foo")) + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack) - assert len(prompt_stack.inputs) == 12 + assert len(prompt_stack.messages) == 12 def test_add_to_prompt_stack_autopruning_enabled(self): # All memory is pruned. @@ -99,42 +100,42 @@ def test_add_to_prompt_stack_autopruning_enabled(self): memory = ConversationMemory( autoprune=True, runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_system_message("fizz") + prompt_stack.add_user_message("foo") + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack) - assert len(prompt_stack.inputs) == 3 + assert len(prompt_stack.messages) == 3 # No memory is pruned. agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=1000))) memory = ConversationMemory( autoprune=True, runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_system_message("fizz") + prompt_stack.add_user_message("foo") + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack) - assert len(prompt_stack.inputs) == 13 + assert len(prompt_stack.messages) == 13 # One memory is pruned. # MockTokenizer's max_input_tokens set to one below the sum of memory + system prompt tokens @@ -144,25 +145,25 @@ def test_add_to_prompt_stack_autopruning_enabled(self): autoprune=True, runs=[ # All of these sum to 155 tokens with the MockTokenizer. - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() # And then another 6 tokens from fizz for a total of 161 tokens. - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_system_message("fizz") + prompt_stack.add_user_message("foo") + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack, 1) - # We expect one run (2 prompt stack inputs) to be pruned. - assert len(prompt_stack.inputs) == 11 - assert prompt_stack.inputs[0].content == "fizz" - assert prompt_stack.inputs[1].content == "foo2" - assert prompt_stack.inputs[2].content == "bar2" - assert prompt_stack.inputs[-2].content == "foo" - assert prompt_stack.inputs[-1].content == "bar" + # We expect one run (2 Prompt Stack inputs) to be pruned. + assert len(prompt_stack.messages) == 11 + assert prompt_stack.messages[0].content[0].artifact.value == "fizz" + assert prompt_stack.messages[1].content[0].artifact.value == "foo2" + assert prompt_stack.messages[2].content[0].artifact.value == "bar2" + assert prompt_stack.messages[-2].content[0].artifact.value == "foo" + assert prompt_stack.messages[-1].content[0].artifact.value == "bar" diff --git a/tests/unit/memory/structure/test_summary_conversation_memory.py b/tests/unit/memory/structure/test_summary_conversation_memory.py index 09792ff5d..e625ac6c6 100644 --- a/tests/unit/memory/structure/test_summary_conversation_memory.py +++ b/tests/unit/memory/structure/test_summary_conversation_memory.py @@ -1,9 +1,9 @@ import json -import pytest from griptape.memory.structure import Run, SummaryConversationMemory from griptape.structures import Pipeline +from griptape.artifacts import TextArtifact from griptape.tasks import PromptTask from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_structure_config import MockStructureConfig @@ -41,36 +41,36 @@ def test_after_run(self): def test_to_json(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert json.loads(memory.to_json())["type"] == "SummaryConversationMemory" - assert json.loads(memory.to_json())["runs"][0]["input"] == "foo" + assert json.loads(memory.to_json())["runs"][0]["input"]["value"] == "foo" def test_to_dict(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert memory.to_dict()["type"] == "SummaryConversationMemory" - assert memory.to_dict()["runs"][0]["input"] == "foo" + assert memory.to_dict()["runs"][0]["input"]["value"] == "foo" def test_to_prompt_stack(self): memory = SummaryConversationMemory(summary="foobar") - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) prompt_stack = memory.to_prompt_stack() - assert prompt_stack.inputs[0].content == "Summary of the conversation so far: foobar" - assert prompt_stack.inputs[1].content == "foo" - assert prompt_stack.inputs[2].content == "bar" + assert prompt_stack.messages[0].content[0].artifact.value == "Summary of the conversation so far: foobar" + assert prompt_stack.messages[1].content[0].artifact.value == "foo" + assert prompt_stack.messages[2].content[0].artifact.value == "bar" def test_from_dict(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(memory.from_dict(memory_dict), SummaryConversationMemory) - assert memory.from_dict(memory_dict).runs[0].input == "foo" - assert memory.from_dict(memory_dict).runs[0].output == "bar" + assert memory.from_dict(memory_dict).runs[0].input.value == "foo" + assert memory.from_dict(memory_dict).runs[0].output.value == "bar" assert memory.from_dict(memory_dict).offset == memory.offset assert memory.from_dict(memory_dict).summary == memory.summary assert memory.from_dict(memory_dict).summary_index == memory.summary_index @@ -78,11 +78,11 @@ def test_from_dict(self): def test_from_json(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(memory.from_dict(memory_dict), SummaryConversationMemory) - assert memory.from_dict(memory_dict).runs[0].input == "foo" + assert memory.from_dict(memory_dict).runs[0].input.value == "foo" def test_config_prompt_driver(self): memory = SummaryConversationMemory() diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index 8bcadb753..942a960f9 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -166,15 +166,15 @@ def test_prompt_stack_without_memory(self): agent.add_task(task1) - assert len(task1.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 agent.run() - assert len(task1.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 agent.run() - assert len(task1.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 def test_prompt_stack_with_memory(self): agent = Agent(prompt_driver=MockPromptDriver(), conversation_memory=ConversationMemory()) @@ -183,15 +183,15 @@ def test_prompt_stack_with_memory(self): agent.add_task(task1) - assert len(task1.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 agent.run() - assert len(task1.prompt_stack.inputs) == 5 + assert len(task1.prompt_stack.messages) == 5 agent.run() - assert len(task1.prompt_stack.inputs) == 7 + assert len(task1.prompt_stack.messages) == 7 def test_run(self): task = PromptTask("test") diff --git a/tests/unit/structures/test_pipeline.py b/tests/unit/structures/test_pipeline.py index d94616165..99c4141bf 100644 --- a/tests/unit/structures/test_pipeline.py +++ b/tests/unit/structures/test_pipeline.py @@ -277,18 +277,18 @@ def test_prompt_stack_without_memory(self): pipeline.add_tasks(task1, task2) - assert len(task1.prompt_stack.inputs) == 2 - assert len(task2.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 + assert len(task2.prompt_stack.messages) == 2 pipeline.run() - assert len(task1.prompt_stack.inputs) == 3 - assert len(task2.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 + assert len(task2.prompt_stack.messages) == 3 pipeline.run() - assert len(task1.prompt_stack.inputs) == 3 - assert len(task2.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 + assert len(task2.prompt_stack.messages) == 3 def test_prompt_stack_with_memory(self): pipeline = Pipeline(prompt_driver=MockPromptDriver()) @@ -298,18 +298,18 @@ def test_prompt_stack_with_memory(self): pipeline.add_tasks(task1, task2) - assert len(task1.prompt_stack.inputs) == 2 - assert len(task2.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 + assert len(task2.prompt_stack.messages) == 2 pipeline.run() - assert len(task1.prompt_stack.inputs) == 5 - assert len(task2.prompt_stack.inputs) == 5 + assert len(task1.prompt_stack.messages) == 5 + assert len(task2.prompt_stack.messages) == 5 pipeline.run() - assert len(task1.prompt_stack.inputs) == 7 - assert len(task2.prompt_stack.inputs) == 7 + assert len(task1.prompt_stack.messages) == 7 + assert len(task2.prompt_stack.messages) == 7 def test_text_artifact_token_count(self): text = "foobar" diff --git a/tests/unit/tasks/test_prompt_task.py b/tests/unit/tasks/test_prompt_task.py index 1dd45ab64..bcef8bce1 100644 --- a/tests/unit/tasks/test_prompt_task.py +++ b/tests/unit/tasks/test_prompt_task.py @@ -1,4 +1,7 @@ import pytest +from griptape.artifacts.image_artifact import ImageArtifact +from griptape.artifacts.list_artifact import ListArtifact +from griptape.artifacts.text_artifact import TextArtifact from tests.mocks.mock_structure_config import MockStructureConfig from griptape.tasks import PromptTask from tests.mocks.mock_prompt_driver import MockPromptDriver @@ -32,3 +35,86 @@ def test_missing_prompt_driver(self): with pytest.raises(ValueError): task.prompt_driver + + def test_input(self): + # Str + task = PromptTask("test") + + assert task.input.value == "test" + + # List of strs + task = PromptTask(["test1", "test2"]) + + assert task.input.value[0].value == "test1" + assert task.input.value[1].value == "test2" + + # Tuple of strs + task = PromptTask(("test1", "test2")) + + assert task.input.value[0].value == "test1" + assert task.input.value[1].value == "test2" + + # Image artifact + task = PromptTask(ImageArtifact(b"image-data", format="png", width=100, height=100)) + + assert isinstance(task.input, ImageArtifact) + assert task.input.value == b"image-data" + assert task.input.format == "png" + assert task.input.width == 100 + assert task.input.height == 100 + + # List of str and image artifact + task = PromptTask(["foo", ImageArtifact(b"image-data", format="png", width=100, height=100)]) + + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 + + # List of str and nested image artifact + task = PromptTask(["foo", [ImageArtifact(b"image-data", format="png", width=100, height=100)]]) + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ListArtifact) + assert isinstance(task.input.value[1].value[0], ImageArtifact) + assert task.input.value[1].value[0].value == b"image-data" + assert task.input.value[1].value[0].format == "png" + assert task.input.value[1].value[0].width == 100 + + # Tuple of str and image artifact + task = PromptTask(("foo", ImageArtifact(b"image-data", format="png", width=100, height=100))) + + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 + + # Lambda returning list of str and image artifact + task = PromptTask( + ListArtifact([TextArtifact("foo"), ImageArtifact(b"image-data", format="png", width=100, height=100)]) + ) + + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 + + # Lambda returning list of str and image artifact + task = PromptTask( + lambda _: ListArtifact( + [TextArtifact("foo"), ImageArtifact(b"image-data", format="png", width=100, height=100)] + ) + ) + + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 diff --git a/tests/unit/tasks/test_toolkit_task.py b/tests/unit/tasks/test_toolkit_task.py index 28cc56ec9..cc05a5caf 100644 --- a/tests/unit/tasks/test_toolkit_task.py +++ b/tests/unit/tasks/test_toolkit_task.py @@ -2,7 +2,7 @@ from griptape.structures import Agent from griptape.tasks import ToolkitTask, ActionsSubtask, PromptTask from tests.mocks.mock_tool.tool import MockTool -from tests.mocks.mock_value_prompt_driver import MockValuePromptDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.utils import defaults @@ -149,7 +149,7 @@ def test_run(self): output = """Answer: done""" task = ToolkitTask("test", tools=[MockTool(name="Tool1"), MockTool(name="Tool2")]) - agent = Agent(prompt_driver=MockValuePromptDriver(value=output)) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=output)) agent.add_task(task) @@ -163,7 +163,7 @@ def test_run_max_subtasks(self): output = """Actions: [{"name": "blah"}]""" task = ToolkitTask("test", tools=[MockTool(name="Tool1")], max_subtasks=3) - agent = Agent(prompt_driver=MockValuePromptDriver(value=output)) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=output)) agent.add_task(task) @@ -176,7 +176,7 @@ def test_run_invalid_react_prompt(self): output = """foo bar""" task = ToolkitTask("test", tools=[MockTool(name="Tool1")], max_subtasks=3) - agent = Agent(prompt_driver=MockValuePromptDriver(value=output)) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=output)) agent.add_task(task) diff --git a/tests/unit/tokenizers/test_google_tokenizer.py b/tests/unit/tokenizers/test_google_tokenizer.py index 955a0517f..34510cdac 100644 --- a/tests/unit/tokenizers/test_google_tokenizer.py +++ b/tests/unit/tokenizers/test_google_tokenizer.py @@ -1,6 +1,7 @@ import pytest from unittest.mock import Mock -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.common.prompt_stack.messages.message import Message from griptape.tokenizers import GoogleTokenizer @@ -19,7 +20,7 @@ def tokenizer(self, request): @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 5)], indirect=["tokenizer"]) def test_token_count(self, tokenizer, expected): assert tokenizer.count_tokens("foo bar huzzah") == expected - assert tokenizer.count_tokens(PromptStack(inputs=[PromptStack.Input(content="foo", role="user")])) == expected + assert tokenizer.count_tokens(PromptStack(messages=[Message(content="foo", role="user")])) == expected assert tokenizer.count_tokens(["foo", "bar", "huzzah"]) == expected @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 30715)], indirect=["tokenizer"]) diff --git a/tests/unit/utils/test_base_tokenizer.py b/tests/unit/utils/test_base_tokenizer.py new file mode 100644 index 000000000..eed15b9b2 --- /dev/null +++ b/tests/unit/utils/test_base_tokenizer.py @@ -0,0 +1,13 @@ +import logging +from tests.mocks.mock_tokenizer import MockTokenizer + + +class TestBaseTokenizer: + def test_default_tokens(self, caplog): + with caplog.at_level(logging.WARNING): + tokenizer = MockTokenizer(model="gpt2") + + assert tokenizer.max_input_tokens == 4096 + assert tokenizer.max_output_tokens == 1000 + + assert "gpt2 not found" in caplog.text diff --git a/tests/unit/utils/test_message_stack.py b/tests/unit/utils/test_message_stack.py new file mode 100644 index 000000000..908388a33 --- /dev/null +++ b/tests/unit/utils/test_message_stack.py @@ -0,0 +1,55 @@ +import pytest + +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact +from griptape.common import ImageMessageContent, PromptStack, TextMessageContent + + +class TestPromptStack: + @pytest.fixture + def prompt_stack(self): + return PromptStack() + + def test_init(self): + assert PromptStack() + + def test_add_message(self, prompt_stack): + prompt_stack.add_message("foo", "role") + prompt_stack.add_message(TextArtifact("foo"), "role") + prompt_stack.add_message(ImageArtifact(b"foo", format="png", width=100, height=100), "role") + prompt_stack.add_message(ListArtifact([TextArtifact("foo"), TextArtifact("bar")]), "role") + + assert prompt_stack.messages[0].role == "role" + assert isinstance(prompt_stack.messages[0].content[0], TextMessageContent) + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + assert prompt_stack.messages[1].role == "role" + assert isinstance(prompt_stack.messages[1].content[0], TextMessageContent) + assert prompt_stack.messages[1].content[0].artifact.value == "foo" + + assert prompt_stack.messages[2].role == "role" + assert isinstance(prompt_stack.messages[2].content[0], ImageMessageContent) + assert prompt_stack.messages[2].content[0].artifact.value == b"foo" + + assert prompt_stack.messages[3].role == "role" + assert isinstance(prompt_stack.messages[3].content[0], TextMessageContent) + assert prompt_stack.messages[3].content[0].artifact.value == "foo" + assert isinstance(prompt_stack.messages[3].content[1], TextMessageContent) + assert prompt_stack.messages[3].content[1].artifact.value == "bar" + + def test_add_system_message(self, prompt_stack): + prompt_stack.add_system_message("foo") + + assert prompt_stack.messages[0].role == "system" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + def test_add_user_message(self, prompt_stack): + prompt_stack.add_user_message("foo") + + assert prompt_stack.messages[0].role == "user" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + def test_add_assistant_message(self, prompt_stack): + prompt_stack.add_assistant_message("foo") + + assert prompt_stack.messages[0].role == "assistant" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" diff --git a/tests/unit/utils/test_prompt_stack.py b/tests/unit/utils/test_prompt_stack.py deleted file mode 100644 index 80010abec..000000000 --- a/tests/unit/utils/test_prompt_stack.py +++ /dev/null @@ -1,41 +0,0 @@ -import pytest -from griptape.utils import PromptStack - - -class TestPromptStack: - @pytest.fixture - def prompt_stack(self): - return PromptStack() - - def test_init(self): - assert PromptStack() - - def test_add_input(self, prompt_stack): - prompt_stack.add_input("foo", "role") - - assert prompt_stack.inputs[0].role == "role" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_generic_input(self, prompt_stack): - prompt_stack.add_generic_input("foo") - - assert prompt_stack.inputs[0].role == "generic" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_system_input(self, prompt_stack): - prompt_stack.add_system_input("foo") - - assert prompt_stack.inputs[0].role == "system" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_user_input(self, prompt_stack): - prompt_stack.add_user_input("foo") - - assert prompt_stack.inputs[0].role == "user" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_assistant_input(self, prompt_stack): - prompt_stack.add_assistant_input("foo") - - assert prompt_stack.inputs[0].role == "assistant" - assert prompt_stack.inputs[0].content == "foo" From 07e2a1c792a8ea7598e70b21eab93d9f621366fe Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Tue, 2 Jul 2024 12:38:25 -0500 Subject: [PATCH 31/87] Add support for Qdrant VectorDB (#928) Co-authored-by: hkhajgiwale Co-authored-by: Harsh Khajgiwale <13365920+hkhajgiwale@users.noreply.github.com> Co-authored-by: Anush --- .github/workflows/docs-integration-tests.yml | 2 + CHANGELOG.md | 1 + .../drivers/vector-store-drivers.md | 62 ++++++ griptape/drivers/__init__.py | 2 + .../vector/qdrant_vector_store_driver.py | 207 ++++++++++++++++++ poetry.lock | 157 ++++++++++++- pyproject.toml | 3 + .../vector/test_qdrant_vector_store_driver.py | 171 +++++++++++++++ 8 files changed, 603 insertions(+), 2 deletions(-) create mode 100644 griptape/drivers/vector/qdrant_vector_store_driver.py create mode 100644 tests/unit/drivers/vector/test_qdrant_vector_store_driver.py diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index 79e0c9f3a..cd21ad1ac 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -120,6 +120,8 @@ jobs: PUSHER_SECRET: ${{ secrets.INTEG_PUSHER_SECRET }} PUSHER_CLUSTER: ${{ secrets.INTEG_PUSHER_CLUSTER }} ZENROWS_API_KEY: ${{ secrets.INTEG_ZENROWS_API_KEY }} + QDRANT_CLUSTER_ENDPOINT: ${{ secrets.INTEG_QDRANT_CLUSTER_ENDPOINT }} + QDRANT_CLUSTER_API_KEY: ${{ secrets.INTEG_QDRANT_CLUSTER_API_KEY }} services: postgres: image: ankane/pgvector:v0.5.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index d8f1a3f2c..399da1969 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -295,6 +295,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `MarkdownifyWebScraperDriver` for scraping text from web pages using playwright and converting to markdown using markdownify. - `VoyageAiEmbeddingDriver` for use with VoyageAi's embedding models. - `AnthropicStructureConfig` for providing Structures with Anthropic Prompt and VoyageAi Embedding Driver configuration. +- `QdrantVectorStoreDriver` to integrate with Qdrant vector databases. ### Fixed - Improved system prompt in `ToolTask` to support more use cases. diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 095c14f22..da6fdc242 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -406,3 +406,65 @@ vector_store_driver.upsert_text_artifacts( result = vector_store_driver.query("What is griptape?") print(result) ``` + +### Qdrant + +!!! info + This driver requires the `drivers-vector-qdrant` [extra](../index.md#extras). + +The QdrantVectorStoreDriver supports the [Qdrant vector database](https://qdrant.tech/). + +Here is an example of how the driver can be used to query information in a Qdrant collection: + +```python +import os +from griptape.drivers import QdrantVectorStoreDriver, HuggingFaceHubEmbeddingDriver +from griptape.tokenizers import HuggingFaceTokenizer +from griptape.loaders import WebLoader + +# Set up environment variables +embedding_model_name = "sentence-transformers/all-MiniLM-L6-v2" +host = os.environ["QDRANT_CLUSTER_ENDPOINT"] +huggingface_token = os.environ["HUGGINGFACE_HUB_ACCESS_TOKEN"] + +# Initialize HuggingFace embedding driver +embedding_driver = HuggingFaceHubEmbeddingDriver( + api_token=huggingface_token, + model=embedding_model_name, + tokenizer=HuggingFaceTokenizer(model=embedding_model_name, max_output_tokens=512), +) + +# Initialize Qdrant vector store driver +vector_store_driver = QdrantVectorStoreDriver( + url=host, + collection_name="griptape", + content_payload_key="content", + embedding_driver=embedding_driver, + api_key=os.environ["QDRANT_CLUSTER_API_KEY"], +) + +# Load data from the website +artifacts = WebLoader().load("https://www.griptape.ai") + +# Encode text to get embeddings +embeddings = embedding_driver.embed_text_artifact(artifacts[0]) + +# Recreate Qdrant collection +vector_store_driver.client.recreate_collection( + collection_name=vector_store_driver.collection_name, + vectors_config={ + "size": len(embeddings), + "distance": vector_store_driver.distance + }, +) + +# Upsert vector into Qdrant +vector_store_driver.upsert_vector( + vector=embeddings, + vector_id=str(artifacts[0].id), + content=artifacts[0].value +) + +print("Vectors successfully inserted into Qdrant.") + +``` diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 34b43103b..fa2934a38 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -39,6 +39,7 @@ from .vector.pgvector_vector_store_driver import PgVectorVectorStoreDriver from .vector.azure_mongodb_vector_store_driver import AzureMongoDbVectorStoreDriver from .vector.dummy_vector_store_driver import DummyVectorStoreDriver +from .vector.qdrant_vector_store_driver import QdrantVectorStoreDriver from .sql.base_sql_driver import BaseSqlDriver from .sql.amazon_redshift_sql_driver import AmazonRedshiftSqlDriver @@ -144,6 +145,7 @@ "OpenSearchVectorStoreDriver", "AmazonOpenSearchVectorStoreDriver", "PgVectorVectorStoreDriver", + "QdrantVectorStoreDriver", "DummyVectorStoreDriver", "BaseSqlDriver", "AmazonRedshiftSqlDriver", diff --git a/griptape/drivers/vector/qdrant_vector_store_driver.py b/griptape/drivers/vector/qdrant_vector_store_driver.py new file mode 100644 index 000000000..5159bdb0a --- /dev/null +++ b/griptape/drivers/vector/qdrant_vector_store_driver.py @@ -0,0 +1,207 @@ +from __future__ import annotations +from typing import Optional +from attrs import define, field +from griptape.drivers import BaseVectorStoreDriver +from griptape.utils import import_optional_dependency +import uuid +import logging + +DEFAULT_DISTANCE = "Cosine" +CONTENT_PAYLOAD_KEY = "data" + + +@define +class QdrantVectorStoreDriver(BaseVectorStoreDriver): + """ + Attributes: + location: An optional location for the Qdrant client. If set to ':memory:', an in-memory client is used. + url: An optional Qdrant API URL. + host: An optional Qdrant host. + path: Persistence path for QdrantLocal. Default: None + port: The port number for the Qdrant client. Defaults: 6333. + grpc_port: The gRPC port number for the Qdrant client. Defaults: 6334. + prefer_grpc: A boolean indicating whether to prefer gRPC over HTTP. Defaults: False. + force_disable_check_same_thread: For QdrantLocal, force disable check_same_thread. Default: False Only use this if you can guarantee that you can resolve the thread safety outside QdrantClient. + timeout: Timeout for REST and gRPC API requests. Default: 5 seconds for REST and unlimited for gRPC + api_key: API key for authentication in Qdrant Cloud. Defaults: False + https: If true - use HTTPS(SSL) protocol. Default: None + prefix: Add prefix to the REST URL path. Example: service/v1 will result in Example: service/v1 will result in http://localhost:6333/service/v1/{qdrant-endpoint} for REST API. Defaults: None + distance: The distance metric to be used for the vectors. Defaults: 'COSINE'. + collection_name: The name of the Qdrant collection. + vector_name: An optional name for the vectors. + content_payload_key: The key for the content payload in the metadata. Defaults: 'data'. + """ + + location: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + url: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + host: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + path: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + port: int = field(default=6333, kw_only=True, metadata={"serializable": True}) + grpc_port: int = field(default=6334, kw_only=True, metadata={"serializable": True}) + prefer_grpc: bool = field(default=False, kw_only=True, metadata={"serializable": True}) + api_key: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + https: bool = field(default=None, kw_only=True, metadata={"serializable": True}) + prefix: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + force_disable_check_same_thread: Optional[bool] = field( + default=False, kw_only=True, metadata={"serializable": True} + ) + timeout: Optional[int] = field(default=5, kw_only=True, metadata={"serializable": True}) + distance: str = field(default=DEFAULT_DISTANCE, kw_only=True, metadata={"serializable": True}) + collection_name: str = field(kw_only=True, metadata={"serializable": True}) + vector_name: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + content_payload_key: str = field(default=CONTENT_PAYLOAD_KEY, kw_only=True, metadata={"serializable": True}) + + def __attrs_post_init__(self) -> None: + self.client = import_optional_dependency("qdrant_client").QdrantClient( + location=self.location, + url=self.url, + host=self.host, + path=self.path, + port=self.port, + prefer_grpc=self.prefer_grpc, + grpc_port=self.grpc_port, + api_key=self.api_key, + https=self.https, + prefix=self.prefix, + force_disable_check_same_thread=self.force_disable_check_same_thread, + timeout=self.timeout, + ) + + def delete_vector(self, vector_id: str) -> None: + """ + Delete a vector from the Qdrant collection based on its ID. + + Parameters: + vector_id (str | id): ID of the vector to delete. + """ + deletion_response = self.client.delete( + collection_name=self.collection_name, + points_selector=import_optional_dependency("qdrant_client.http.models").PointIdsList(points=[vector_id]), + ) + if deletion_response.status == import_optional_dependency("qdrant_client.http.models").UpdateStatus.COMPLETED: + logging.info(f"ID {vector_id} is successfully deleted") + + def query( + self, + query: str, + count: Optional[int] = None, + namespace: Optional[str] = None, + include_vectors: bool = False, + **kwargs, + ) -> list[BaseVectorStoreDriver.Entry]: + """ + Query the Qdrant collection based on a query vector. + + Parameters: + query (str): Query string. + count (Optional[int]): Optional number of results to return. + namespace (Optional[str]): Optional namespace of the vectors. + include_vectors (bool): Whether to include vectors in the results. + + Returns: + list[BaseVectorStoreDriver.Entry]: List of Entry objects. + """ + query_vector = self.embedding_driver.embed_string(query) + + # Create a search request + results = self.client.search(collection_name=self.collection_name, query_vector=query_vector, limit=count) + + # Convert results to QueryResult objects + query_results = [ + BaseVectorStoreDriver.Entry( + id=result.id, + vector=result.vector if include_vectors else [], + score=result.score, + meta={k: v for k, v in result.payload.items() if k not in ["_score", "_tensor_facets"]}, + ) + for result in results + ] + return query_results + + def upsert_vector( + self, + vector: list[float], + vector_id: Optional[str] = None, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + content: Optional[str] = None, + **kwargs, + ) -> str: + """ + Upsert vectors into the Qdrant collection. + + Parameters: + vector (list[float]): The vector to be upserted. + vector_id (Optional[str]): Optional vector ID. + namespace (Optional[str]): Optional namespace for the vector. + meta (Optional[dict]): Optional dictionary containing metadata. + content (Optional[str]): The text content to be included in the payload. + + Returns: + str: The ID of the upserted vector. + """ + + if vector_id is None: + vector_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, str(vector))) + + if meta is None: + meta = {} + + if content: + meta[self.content_payload_key] = content + + points = import_optional_dependency("qdrant_client.http.models").Batch( + ids=[vector_id], vectors=[vector], payloads=[meta] if meta else None + ) + + self.client.upsert(collection_name=self.collection_name, points=points) + return vector_id + + def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + """ + Load a vector entry from the Qdrant collection based on its ID. + + Parameters: + vector_id (str): ID of the vector to load. + namespace (str, optional): Optional namespace of the vector. + + Returns: + Optional[BaseVectorStoreDriver.Entry]: Vector entry if found, else None. + """ + results = self.client.retrieve(collection_name=self.collection_name, ids=[vector_id]) + if results: + entry = results[0] + return BaseVectorStoreDriver.Entry( + id=entry.id, + vector=entry.vector, + meta={k: v for k, v in entry.payload.items() if k not in ["_score", "_tensor_facets"]}, + ) + else: + return None + + def load_entries(self, namespace: Optional[str] = None, **kwargs) -> list[BaseVectorStoreDriver.Entry]: + """ + Load vector entries from the Qdrant collection. + + Parameters: + namespace: Optional namespace of the vectors. + + Returns: + List of points. + """ + + results = self.client.retrieve( + collection_name=self.collection_name, + ids=kwargs.get("ids", []), + with_payload=kwargs.get("with_payload", True), + with_vectors=kwargs.get("with_vectors", True), + ) + + return [ + BaseVectorStoreDriver.Entry( + id=entry.id, + vector=entry.vector if kwargs.get("with_vectors", True) else [], + meta={k: v for k, v in entry.payload.items() if k not in ["_score", "_tensor_facets"]}, + ) + for entry in results + ] diff --git a/poetry.lock b/poetry.lock index 768a4e8ae..64f01aa75 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1844,6 +1844,74 @@ googleapis-common-protos = ">=1.5.5" grpcio = ">=1.62.2" protobuf = ">=4.21.6" +[[package]] +name = "grpcio-tools" +version = "1.62.2" +description = "Protobuf code generator for gRPC" +optional = true +python-versions = ">=3.7" +files = [ + {file = "grpcio-tools-1.62.2.tar.gz", hash = "sha256:5fd5e1582b678e6b941ee5f5809340be5e0724691df5299aae8226640f94e18f"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-linux_armv7l.whl", hash = "sha256:1679b4903aed2dc5bd8cb22a452225b05dc8470a076f14fd703581efc0740cdb"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:9d41e0e47dd075c075bb8f103422968a65dd0d8dc8613288f573ae91eb1053ba"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:987e774f74296842bbffd55ea8826370f70c499e5b5f71a8cf3103838b6ee9c3"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd4eeea4b25bcb6903b82930d579027d034ba944393c4751cdefd9c49e6989"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6746bc823958499a3cf8963cc1de00072962fb5e629f26d658882d3f4c35095"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2ed775e844566ce9ce089be9a81a8b928623b8ee5820f5e4d58c1a9d33dfc5ae"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bdc5dd3f57b5368d5d661d5d3703bcaa38bceca59d25955dff66244dbc987271"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-win32.whl", hash = "sha256:3a8d6f07e64c0c7756f4e0c4781d9d5a2b9cc9cbd28f7032a6fb8d4f847d0445"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-win_amd64.whl", hash = "sha256:e33b59fb3efdddeb97ded988a871710033e8638534c826567738d3edce528752"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-linux_armv7l.whl", hash = "sha256:472505d030135d73afe4143b0873efe0dcb385bd6d847553b4f3afe07679af00"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:ec674b4440ef4311ac1245a709e87b36aca493ddc6850eebe0b278d1f2b6e7d1"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:184b4174d4bd82089d706e8223e46c42390a6ebac191073b9772abc77308f9fa"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c195d74fe98541178ece7a50dad2197d43991e0f77372b9a88da438be2486f12"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a34d97c62e61bfe9e6cff0410fe144ac8cca2fc979ad0be46b7edf026339d161"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb8453ae83a1db2452b7fe0f4b78e4a8dd32be0f2b2b73591ae620d4d784d3d"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f989e5cebead3ae92c6abf6bf7b19949e1563a776aea896ac5933f143f0c45d"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-win32.whl", hash = "sha256:c48fabe40b9170f4e3d7dd2c252e4f1ff395dc24e49ac15fc724b1b6f11724da"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c616d0ad872e3780693fce6a3ac8ef00fc0963e6d7815ce9dcfae68ba0fc287"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-linux_armv7l.whl", hash = "sha256:10cc3321704ecd17c93cf68c99c35467a8a97ffaaed53207e9b2da6ae0308ee1"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:9be84ff6d47fd61462be7523b49d7ba01adf67ce4e1447eae37721ab32464dd8"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:d82f681c9a9d933a9d8068e8e382977768e7779ddb8870fa0cf918d8250d1532"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04c607029ae3660fb1624ed273811ffe09d57d84287d37e63b5b802a35897329"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72b61332f1b439c14cbd3815174a8f1d35067a02047c32decd406b3a09bb9890"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8214820990d01b52845f9fbcb92d2b7384a0c321b303e3ac614c219dc7d1d3af"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:462e0ab8dd7c7b70bfd6e3195eebc177549ede5cf3189814850c76f9a340d7ce"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-win32.whl", hash = "sha256:fa107460c842e4c1a6266150881694fefd4f33baa544ea9489601810c2210ef8"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-win_amd64.whl", hash = "sha256:759c60f24c33a181bbbc1232a6752f9b49fbb1583312a4917e2b389fea0fb0f2"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-linux_armv7l.whl", hash = "sha256:45db5da2bcfa88f2b86b57ef35daaae85c60bd6754a051d35d9449c959925b57"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:ab84bae88597133f6ea7a2bdc57b2fda98a266fe8d8d4763652cbefd20e73ad7"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:7a49bccae1c7d154b78e991885c3111c9ad8c8fa98e91233de425718f47c6139"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7e439476b29d6dac363b321781a113794397afceeb97dad85349db5f1cb5e9a"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ea369c4d1567d1acdf69c8ea74144f4ccad9e545df7f9a4fc64c94fa7684ba3"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f955702dc4b530696375251319d05223b729ed24e8673c2129f7a75d2caefbb"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3708a747aa4b6b505727282ca887041174e146ae030ebcadaf4c1d346858df62"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2ce149ea55eadb486a7fb75a20f63ef3ac065ee6a0240ed25f3549ce7954c653"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-linux_armv7l.whl", hash = "sha256:58cbb24b3fa6ae35aa9c210fcea3a51aa5fef0cd25618eb4fd94f746d5a9b703"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:6413581e14a80e0b4532577766cf0586de4dd33766a31b3eb5374a746771c07d"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:47117c8a7e861382470d0e22d336e5a91fdc5f851d1db44fa784b9acea190d87"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f1ba79a253df9e553d20319c615fa2b429684580fa042dba618d7f6649ac7e4"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04a394cf5e51ba9be412eb9f6c482b6270bd81016e033e8eb7d21b8cc28fe8b5"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3c53b221378b035ae2f1881cbc3aca42a6075a8e90e1a342c2f205eb1d1aa6a1"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c384c838b34d1b67068e51b5bbe49caa6aa3633acd158f1ab16b5da8d226bc53"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-win32.whl", hash = "sha256:19ea69e41c3565932aa28a202d1875ec56786aea46a2eab54a3b28e8a27f9517"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-win_amd64.whl", hash = "sha256:1d768a5c07279a4c461ebf52d0cec1c6ca85c6291c71ec2703fe3c3e7e28e8c4"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-linux_armv7l.whl", hash = "sha256:5b07b5874187e170edfbd7aa2ca3a54ebf3b2952487653e8c0b0d83601c33035"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:d58389fe8be206ddfb4fa703db1e24c956856fcb9a81da62b13577b3a8f7fda7"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:7d8b4e00c3d7237b92260fc18a561cd81f1da82e8be100db1b7d816250defc66"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe08d2038f2b7c53259b5c49e0ad08c8e0ce2b548d8185993e7ef67e8592cca"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19216e1fb26dbe23d12a810517e1b3fbb8d4f98b1a3fbebeec9d93a79f092de4"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b8574469ecc4ff41d6bb95f44e0297cdb0d95bade388552a9a444db9cd7485cd"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4f6f32d39283ea834a493fccf0ebe9cfddee7577bdcc27736ad4be1732a36399"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-win32.whl", hash = "sha256:76eb459bdf3fb666e01883270beee18f3f11ed44488486b61cd210b4e0e17cc1"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-win_amd64.whl", hash = "sha256:217c2ee6a7ce519a55958b8622e21804f6fdb774db08c322f4c9536c35fdce7c"}, +] + +[package.dependencies] +grpcio = ">=1.62.2" +protobuf = ">=4.21.6,<5.0dev" +setuptools = "*" + [[package]] name = "h11" version = "0.14.0" @@ -1855,6 +1923,32 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[package]] +name = "h2" +version = "4.1.0" +description = "HTTP/2 State-Machine based protocol implementation" +optional = true +python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] + +[package.dependencies] +hpack = ">=4.0,<5" +hyperframe = ">=6.0,<7" + +[[package]] +name = "hpack" +version = "4.0.0" +description = "Pure-Python HPACK header compression" +optional = true +python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] + [[package]] name = "htmldate" version = "1.8.1" @@ -1926,6 +2020,7 @@ files = [ [package.dependencies] anyio = "*" certifi = "*" +h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} httpcore = "==1.*" idna = "*" sniffio = "*" @@ -1981,6 +2076,17 @@ testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gr torch = ["safetensors", "torch"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] +[[package]] +name = "hyperframe" +version = "6.0.1" +description = "HTTP/2 framing layer for Python" +optional = true +python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] + [[package]] name = "identify" version = "2.5.36" @@ -3787,6 +3893,25 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "portalocker" +version = "2.8.2" +description = "Wraps the portalocker recipe for easy usage" +optional = true +python-versions = ">=3.8" +files = [ + {file = "portalocker-2.8.2-py3-none-any.whl", hash = "sha256:cfb86acc09b9aa7c3b43594e19be1345b9d16af3feb08bf92f23d4dce513a28e"}, + {file = "portalocker-2.8.2.tar.gz", hash = "sha256:2b035aa7828e46c58e9b31390ee1f169b98e1066ab10b9a6a861fe7e25ee4f33"}, +] + +[package.dependencies] +pywin32 = {version = ">=226", markers = "platform_system == \"Windows\""} + +[package.extras] +docs = ["sphinx (>=1.7.1)"] +redis = ["redis"] +tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)", "types-redis"] + [[package]] name = "pprintpp" version = "0.4.0" @@ -4597,6 +4722,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -4645,6 +4771,32 @@ files = [ [package.dependencies] pyyaml = "*" +[[package]] +name = "qdrant-client" +version = "1.9.1" +description = "Client library for the Qdrant vector search engine" +optional = true +python-versions = ">=3.8" +files = [ + {file = "qdrant_client-1.9.1-py3-none-any.whl", hash = "sha256:b9b7e0e5c1a51410d8bb5106a869a51e12f92ab45a99030f27aba790553bd2c8"}, + {file = "qdrant_client-1.9.1.tar.gz", hash = "sha256:186b9c31d95aefe8f2db84b7746402d7365bd63b305550e530e31bde2002ce79"}, +] + +[package.dependencies] +grpcio = ">=1.41.0" +grpcio-tools = ">=1.41.0" +httpx = {version = ">=0.20.0", extras = ["http2"]} +numpy = [ + {version = ">=1.21", markers = "python_version >= \"3.8\" and python_version < \"3.12\""}, + {version = ">=1.26", markers = "python_version >= \"3.12\""}, +] +portalocker = ">=2.7.0,<3.0.0" +pydantic = ">=1.10.8" +urllib3 = ">=1.26.14,<3" + +[package.extras] +fastembed = ["fastembed (==0.2.6)"] + [[package]] name = "readme-renderer" version = "43.0" @@ -6369,7 +6521,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] @@ -6399,6 +6551,7 @@ drivers-vector-mongodb = ["pymongo"] drivers-vector-opensearch = ["opensearch-py"] drivers-vector-pinecone = ["pinecone-client"] drivers-vector-postgresql = ["pgvector", "psycopg2-binary"] +drivers-vector-qdrant = ["qdrant-client"] drivers-vector-redis = ["redis"] drivers-web-scraper-markdownify = ["beautifulsoup4", "markdownify", "playwright"] drivers-web-scraper-trafilatura = ["trafilatura"] @@ -6412,4 +6565,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "937d5e870407a493038178b3060c663feb9a1b6e6fc16e55fa380a18d02b0c80" +content-hash = "d4a00633119a6b9616fc0ea31ae354f806d1fc363e4a930fa912d2d710aa8938" diff --git a/pyproject.toml b/pyproject.toml index 7882790cd..be33acb39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ markdownify = {version = "^0.11.6", optional = true} voyageai = {version = "^0.2.1", optional = true} elevenlabs = {version = "^1.1.2", optional = true} torch = {version = "^2.3.0", optional = true} +qdrant-client = { version = ">=1.9.1", optional = true } pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} duckduckgo-search = {version = "^6.1.6", optional = true} @@ -87,6 +88,7 @@ drivers-vector-redis = ["redis"] drivers-vector-opensearch = ["opensearch-py"] drivers-vector-amazon-opensearch = ["opensearch-py", "boto3"] drivers-vector-postgresql = ["pgvector", "psycopg2-binary"] +drivers-vector-qdrant = ["qdrant-client"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] @@ -124,6 +126,7 @@ all = [ "snowflake", "marqo", "pinecone-client", + "qdrant-client", "pymongo", "redis", "opensearch-py", diff --git a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py new file mode 100644 index 000000000..4431b146f --- /dev/null +++ b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py @@ -0,0 +1,171 @@ +import pytest +from unittest.mock import MagicMock, patch +from griptape.drivers import QdrantVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from griptape.utils import import_optional_dependency +import uuid + + +class TestQdrantVectorStoreDriver: + @pytest.fixture + def embedding_driver(self): + return MockEmbeddingDriver() + + @pytest.fixture + def mock_engine(self): + return MagicMock() + + @pytest.fixture(autouse=True) + def driver(self, embedding_driver): + driver = QdrantVectorStoreDriver( + url="http://some_url", + port=8080, + grpc_port=50051, + prefer_grpc=True, + api_key=None, + https=False, + prefix=None, + force_disable_check_same_thread=False, + timeout=5, + distance="COSINE", + collection_name="some_collection", + vector_name=None, + content_payload_key="data", + embedding_driver=embedding_driver, + ) + return driver + + def test_attrs_post_init(self, driver): + with patch("griptape.drivers.vector.qdrant_vector_store_driver.import_optional_dependency") as mock_import: + mock_qdrant_client = MagicMock() + mock_import.return_value.QdrantClient.return_value = mock_qdrant_client + + driver.__attrs_post_init__() + + mock_import.assert_called_once_with("qdrant_client") + mock_import.return_value.QdrantClient.assert_called_once_with( + location=driver.location, + url=driver.url, + host=driver.host, + path=driver.path, + port=driver.port, + prefer_grpc=driver.prefer_grpc, + grpc_port=driver.grpc_port, + api_key=driver.api_key, + https=driver.https, + prefix=driver.prefix, + force_disable_check_same_thread=driver.force_disable_check_same_thread, + timeout=driver.timeout, + ) + assert driver.client == mock_qdrant_client + + def test_delete_vector(self, driver): + vector_id = "test_vector_id" + + mock_deletion_response = MagicMock() + mock_deletion_response.status = import_optional_dependency("qdrant_client.http.models").UpdateStatus.COMPLETED + + with patch.object(driver.client, "delete", return_value=mock_deletion_response) as mock_delete, patch( + "griptape.drivers.vector.qdrant_vector_store_driver.import_optional_dependency" + ) as mock_import: + mock_import.return_value.PointIdsList.return_value = MagicMock() + mock_import.return_value.UpdateStatus = import_optional_dependency("qdrant_client.http.models").UpdateStatus + + driver.delete_vector(vector_id) + + mock_delete.assert_called_once_with( + collection_name=driver.collection_name, + points_selector=mock_import.return_value.PointIdsList(points=[vector_id]), + ) + + def test_query(self, driver): + mock_query_result = [ + MagicMock( + id="foo", vector=[0, 1, 0], score=42, payload={"foo": "bar", "_score": 0.99, "_tensor_facets": []} + ) + ] + + with patch.object( + driver.embedding_driver, "embed_string", return_value=[0.1, 0.2, 0.3] + ) as mock_embed, patch.object(driver.client, "search", return_value=mock_query_result) as mock_search: + query = "test" + count = 10 + include_vectors = True + + results = driver.query(query, count, include_vectors=include_vectors) + + mock_embed.assert_called_once_with(query) + mock_search.assert_called_once_with( + collection_name=driver.collection_name, query_vector=[0.1, 0.2, 0.3], limit=count + ) + + assert len(results) == 1 + assert results[0].id == "foo" + assert results[0].vector == [0, 1, 0] if include_vectors else [] + assert results[0].score == 42 + assert results[0].meta == {"foo": "bar"} + + def test_upsert_with_batch(self, driver): + vector = [0.1, 0.2, 0.3] + vector_id = str(uuid.uuid4()) + meta = {"meta_key": "meta_value"} + + with patch("griptape.drivers.vector.qdrant_vector_store_driver.import_optional_dependency") as mock_import: + mock_batch = MagicMock() + mock_import.return_value.Batch.return_value = mock_batch + mock_qdrant_client = MagicMock() + driver.client = mock_qdrant_client + + result = driver.upsert_vector(vector=vector, vector_id=vector_id, meta=meta) + + mock_import.assert_called_once_with("qdrant_client.http.models") + mock_import.return_value.Batch.assert_called_once_with(ids=[vector_id], vectors=[vector], payloads=[meta]) + driver.client.upsert.assert_called_once_with(collection_name=driver.collection_name, points=mock_batch) + assert result == vector_id + + def test_load_entry(self, driver): + vector_id = str(uuid.uuid4()) + mock_entry = MagicMock() + mock_entry.id = vector_id + mock_entry.vector = [0.1, 0.2, 0.3] + mock_entry.payload = {"meta_key": "meta_value", "_score": 0.99, "_tensor_facets": []} + + with patch.object(driver.client, "retrieve", return_value=[mock_entry]): + result = driver.load_entry(vector_id) + + driver.client.retrieve.assert_called_once_with(collection_name=driver.collection_name, ids=[vector_id]) + + assert result.id == vector_id + assert result.vector == [0.1, 0.2, 0.3] + assert result.meta == {"meta_key": "meta_value"} + + with patch.object(driver.client, "retrieve", return_value=[]): + result = driver.load_entry(vector_id) + + driver.client.retrieve.assert_called_with(collection_name=driver.collection_name, ids=[vector_id]) + assert result is None + + def test_load_entries(self, driver): + mock_entries = [ + MagicMock( + id="id1", vector=[0.1, 0.2, 0.3], payload={"key1": "value1", "_score": 0.99, "_tensor_facets": []} + ), + MagicMock( + id="id2", vector=[0.4, 0.5, 0.6], payload={"key2": "value2", "_score": 0.88, "_tensor_facets": []} + ), + ] + + with patch.object(driver.client, "retrieve", return_value=mock_entries) as mock_retrieve: + results = driver.load_entries(ids=["id1", "id2"], with_payload=True, with_vectors=True) + + mock_retrieve.assert_called_once_with( + collection_name=driver.collection_name, ids=["id1", "id2"], with_payload=True, with_vectors=True + ) + + assert len(results) == 2 + assert results[0].id == "id1" + assert results[0].vector == [0.1, 0.2, 0.3] + assert results[0].meta == {"key1": "value1"} + assert results[1].id == "id2" + assert results[1].vector == [0.4, 0.5, 0.6] + assert results[1].meta == {"key2": "value2"} From ef46d1e2de061d551b70336fd530a325954a80ef Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 2 Jul 2024 16:38:23 -0500 Subject: [PATCH 32/87] Update contributing guidelines (#927) --- .github/pull_request_template.md | 7 ++----- Makefile | 8 ++++++-- README.md | 26 +++++++++++++++++--------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 3a3496ef6..71a920fcf 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,8 +1,5 @@ +- [ ] I have read and agree to the contributing guidelines for [submitting new pull requests](https://github.com/griptape-ai/griptape?tab=readme-ov-file#submitting-pull-requests). + ## Describe your changes ## Issue ticket number and link - -## Checklist before requesting a review -- [ ] I have performed a self-review of my code. -- [ ] I have added thorough tests. -- [ ] Is this a notable change? If so, please update the [changelog](https://github.com/griptape-ai/griptape/blob/dev/CHANGELOG.md). diff --git a/Makefile b/Makefile index 57d1869ce..13410094c 100644 --- a/Makefile +++ b/Makefile @@ -16,8 +16,8 @@ publish: ## Push git tag and publish version to PyPI. install: ## Install all dependencies. @poetry install --with dev --with test --with docs --all-extras -.PHONY: test -test: test/unit test/integration ## Run all tests. +.PHONY: test ## Run all tests. +test: test/unit test/integration .PHONY: test/unit test/unit: ## Run unit tests. @@ -57,6 +57,10 @@ check/types: .PHONY: check/spell check/spell: @poetry run typos + +.PHONY: docs +docs: ## Build documentation. + @poetry run mkdocs build .DEFAULT_GOAL := help .PHONY: help diff --git a/README.md b/README.md index 6905903a3..3f2a895ab 100644 --- a/README.md +++ b/README.md @@ -162,12 +162,6 @@ Thank you for considering contributing to Griptape! Before you start, please rea If you have identified a bug, want to propose a new feature, or have a question, please submit an issue through our public [issue tracker](https://github.com/griptape-ai/griptape/issues). Before submitting a new issue, please check the existing issues to ensure it hasn't been reported or discussed before. -### New Griptape Tools - -Griptape's extensibility allows anyone to develop and distribute tools independently. With rare exceptions for Tools providing broadly applicable functionality, new Griptape Tools should be managed as their own projects and not submitted to the core framework. Pull requests for new tools (unless addressing an [existing issue](https://github.com/griptape-ai/griptape/issues)) will be closed. - -The [Griptape Tool Template](https://github.com/griptape-ai/tool-template) provides the recommended structure, step-by-step instructions, basic automation, and usage examples for new Tools. In the Template, select **Use this template** then **Create a new repository** to begin a new Tool project. - ### Submitting Pull Requests We welcome and encourage pull requests. To streamline the process, please follow these guidelines: @@ -178,13 +172,27 @@ We welcome and encourage pull requests. To streamline the process, please follow 3. **Unit Tests:** Ensure that your pull request passes all existing unit tests. Additionally, if you are introducing new code, please include new unit tests to validate its functionality. +Run `make test/unit` to execute the test suite locally. + 4. **Documentation:** Every pull request must include updates to documentation or explicitly explain why a documentation update is not required. Documentation is crucial for maintaining a comprehensive and user-friendly project. -5. **Code Style:** Griptape uses [Ruff](https://github.com/astral-sh/ruff) to enforce style guidelines. You can ensure that your code is formatted accordingly and will pass formatting checks using `pre-commit`. See [Tools](#tools) for information on how to configure this and other dev tools. +Run `make docs` to build the documentation locally. + +5. **Code Checks:** Griptape a variety of tools to enforce code quality and style. Your code must pass all checks before it can be merged. + +Run `make check` to run all code checks locally. + +6. **Changelog:** If your pull request introduces a notable change, please update the [changelog](https://github.com/griptape-ai/griptape/blob/dev/CHANGELOG.md). + +### New Griptape Tools + +Griptape's extensibility allows anyone to develop and distribute tools independently. With rare exceptions for Tools providing broadly applicable functionality, new Griptape Tools should be managed as their own projects and not submitted to the core framework. Pull requests for new tools (unless addressing an [existing issue](https://github.com/griptape-ai/griptape/issues)) will be closed. + +The [Griptape Tool Template](https://github.com/griptape-ai/tool-template) provides the recommended structure, step-by-step instructions, basic automation, and usage examples for new Tools. In the Template, select **Use this template** then **Create a new repository** to begin a new Tool project. -### Tools +### Dev and Test Dependencies -Install dev dependencies via Make: +Install all dependencies via Make: ```shell make install From 748744194c257e882c6c622826ea6faa82766a92 Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Tue, 2 Jul 2024 18:19:05 -0500 Subject: [PATCH 33/87] Fix integration tests; Update `PromptTask` input validation (#931) --- docs/griptape-framework/drivers/prompt-drivers.md | 2 +- docs/griptape-tools/official-tools/date-time.md | 4 +--- .../drivers/vector/base_vector_store_driver.py | 8 ++++++-- griptape/tasks/prompt_task.py | 4 +--- poetry.lock | 14 +------------- .../vector/test_pinecone_vector_storage_driver.py | 2 +- .../vector/test_qdrant_vector_store_driver.py | 3 ++- tests/unit/tasks/test_prompt_task.py | 6 +++++- 8 files changed, 18 insertions(+), 25 deletions(-) diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index f95a0ba4e..a846cbb5b 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -36,7 +36,7 @@ stack = PromptStack() stack.add_system_message( "You will be provided with Python code, and your task is to calculate its time complexity." ) -stack.add_user_input( +stack.add_user_message( """ def foo(n, k): accum = 0 diff --git a/docs/griptape-tools/official-tools/date-time.md b/docs/griptape-tools/official-tools/date-time.md index 6ecf6e2a6..aa0c0cc55 100644 --- a/docs/griptape-tools/official-tools/date-time.md +++ b/docs/griptape-tools/official-tools/date-time.md @@ -12,9 +12,7 @@ agent = Agent( ) # Fetch the current date and time -agent.run({ - "description": "What is the current date and time?" -}) +agent.run("What is the current date and time?") ``` ``` [09/11/23 15:26:02] INFO Task d0bf49dacd8849e695494578a333f6cc diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 2c0962328..5a4130a88 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -1,4 +1,5 @@ from __future__ import annotations +import uuid from abc import ABC, abstractmethod from concurrent import futures from dataclasses import dataclass @@ -56,7 +57,7 @@ def upsert_text_artifact( **kwargs, ) -> str: meta = {} if meta is None else meta - vector_id = utils.str_to_hash(artifact.to_text()) if vector_id is None else vector_id + vector_id = self._get_default_vector_id(artifact.to_text()) if vector_id is None else vector_id if self.does_entry_exist(vector_id, namespace): return vector_id @@ -81,7 +82,7 @@ def upsert_text( meta: Optional[dict] = None, **kwargs, ) -> str: - vector_id = utils.str_to_hash(string) if vector_id is None else vector_id + vector_id = self._get_default_vector_id(string) if vector_id is None else vector_id if self.does_entry_exist(vector_id, namespace): return vector_id @@ -134,3 +135,6 @@ def query( include_vectors: bool = False, **kwargs, ) -> list[Entry]: ... + + def _get_default_vector_id(self, value: str) -> str: + return str(uuid.uuid5(uuid.NAMESPACE_OID, value)) diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index f10899f76..dba542d60 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -100,11 +100,9 @@ def _process_task_input( return task_input elif isinstance(task_input, Callable): return self._process_task_input(task_input(self)) - elif isinstance(task_input, str): - return self._process_task_input(TextArtifact(task_input)) elif isinstance(task_input, BaseArtifact): return task_input elif isinstance(task_input, list) or isinstance(task_input, tuple): return ListArtifact([self._process_task_input(elem) for elem in task_input]) else: - raise ValueError(f"Invalid input type: {type(task_input)} ") + return self._process_task_input(TextArtifact(task_input)) diff --git a/poetry.lock b/poetry.lock index 64f01aa75..1d925d6a1 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohttp" @@ -4463,48 +4463,37 @@ files = [ {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab6b32544491ee655264dab86fc8a58e47c4f87d196b28022d4007faf971a50"}, {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:64bd6299e7fc888bb7f7292cf3e29504c406e5d5d04afd37ca994ab8142d8ee4"}, {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e914b650dd953b8d9b24ef56aa4ecbfc16e399227b68accd818f8bf159e0c558"}, - {file = "pyreqwest_impersonate-0.4.8-cp310-none-win_amd64.whl", hash = "sha256:cb56a2149b0c4548a8e0158b071a943f33dae9b717f92b5c9ac34ccd1f5a958c"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f62620e023490902feca0109f306e122e427feff7d59e03ecd22c69a89452367"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:08d4c01d76da88cfe3d7d03b311b375ce3fb5a59130f93f0637bb755d6e56ff1"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524e276bc460176c79d7ba4b9131d9db73c534586660371ebdf067749252a33"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22863bc0aaf02ca2f5d76c8130929ae680b7d82dfc1c28c1ed5f306ff626928"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8cc82d57f6a91037e64a7aa9122f909576ef2a141a42ce599958ef9f8c4bc033"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da8a053308210e44fd8349f07f45442a0691ac932f2881e98b05cf9ac404b091"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-none-win_amd64.whl", hash = "sha256:4baf3916c14364a815a64ead7f728afb61b37541933b2771f18dbb245029bb55"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:78db05deed0b32c9c75f2b3168a3a9b7d5e36487b218cb839bfe7e2a143450cb"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9af9446d605903c2b4e94621a9093f8d8a403729bc9cbfbcb62929f8238c838f"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c55890181d8d81e66cac25a95e215dc9680645d01e9091b64449d5407ad9bc6"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69344e7ae9964502a8693da7ad77ebc3e1418ee197e2e394bc23c5d4970772a"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b5db5c957a10d8cc2815085ba0b8fe09245b2f94c2225d9653a854a03b4217e1"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03c19c21f63f9c91c590c4bbcc32cc2d8066b508c683a1d163b8c7d9816a01d5"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-none-win_amd64.whl", hash = "sha256:0230610779129f74ff802c744643ce7589b1d07cba21d046fe3b574281c29581"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b8cb9471ab4b2fa7e80d3ac4e580249ff988d782f2938ad1f0428433652b170d"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8081a5ace2658be91519902bde9ddc5f94e1f850a39be196007a25e3da5bbfdc"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69eababfa3200459276acd780a0f3eaf41d1fe7c02bd169e714cba422055b5b9"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632957fa671ebb841166e40913015de457225cb73600ef250c436c280e68bf45"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2ce7ddef334b4e5c68f5ea1da1d65f686b8d84f4443059d128e0f069d3fa499a"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6ce333d450b158d582e36317089a006440b4e66739a8e8849d170e4cb15e8c8d"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-none-win_amd64.whl", hash = "sha256:9d9c85ce19db92362854f534807e470f03e905f283a7de6826dc79b790a8788e"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2503277f2a95a30e28e498570e2ed03ef4302f873054e8e21d6c0e607cbbc1d1"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8260395ef4ddae325e8b30cef0391adde7bd35e1a1decf8c729e26391f09b52d"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d8066b46d82bbaff5402d767e2f13d3449b8191c37bf8283e91d301a7159869"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9c42f6343cfbd6663fb53edc9eb9feb4ebf6186b284e22368adc1eeb6a33854"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff534f491a059e74fb7f994876df86078b4b125dbecc53c098a298ecd55fa9c6"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b8fbf73b3ac513ddadafd338d61f79cd2370f0691d9175b2b92a45920920d6b"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-none-win_amd64.whl", hash = "sha256:a26447c82665d0e361207c1a15e56b0ca54974aa6c1fdfa18c68f908dec78cbe"}, {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24a16b8d55309f0af0db9d04ff442b0c91afccf078a94809e7c3a71747a5c214"}, {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c8fada56465fc19179404cc9d5d5e1064f5dfe27405cb052f57a5b4fe06aed1"}, {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a3d48d5abc146fd804395713427d944757a99254350e6a651e7d776818074aee"}, - {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:475829fe9994c66258157a8d4adb1c038f44f79f901208ba656d547842337227"}, {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef1ec0e97623bc0e18469418cc4dd2c59a2d5fddcae944de61e13c0b46f910e"}, {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91857b196de89e9b36d3f8629aa8772c0bbe7efef8334fe266956b1c192ec31c"}, {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:63831e407487b8a21bb51f97cd86a616c291d5138f8caec16ab6019cf6423935"}, - {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c30e61de93bcd0a9d3ca226b1ae5475002afde61e9d85018a6a4a040eeb86567"}, {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c72c37b03bce9900f5dbb4f476af17253ec60c13bf7a7259f71a8dc1b036cb"}, {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f1096165741b5c2178ab15b0eb09b5de16dd39b1cc135767d72471f0a69ce"}, {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:70c940c0e4ef335e22a6c705b01f286ee44780b5909065d212d94d82ea2580cb"}, - {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81c06f21757602d85f16dbc1cbaee1121cd65455f65aed4c048b7dcda7be85c4"}, - {file = "pyreqwest_impersonate-0.4.8.tar.gz", hash = "sha256:1eba11d47bd17244c64fec1502cc26ee66cc5c8a3be131e408101ae2b455e5bc"}, ] [package.extras] @@ -4722,7 +4711,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, diff --git a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py index c0477fe97..7aea4d411 100644 --- a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py +++ b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py @@ -34,7 +34,7 @@ def driver(self): def test_upsert_text_artifact(self, driver): artifact = TextArtifact("foo") - assert driver.upsert_text_artifact(artifact) == utils.str_to_hash(artifact.value) + assert driver.upsert_text_artifact(artifact) == driver._get_default_vector_id("foo") def test_upsert_vector(self, driver): assert driver.upsert_vector([0, 1, 2], vector_id="foo") == "foo" diff --git a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py index 4431b146f..c999af8b9 100644 --- a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py @@ -16,7 +16,8 @@ def mock_engine(self): return MagicMock() @pytest.fixture(autouse=True) - def driver(self, embedding_driver): + def driver(self, embedding_driver, mocker): + mocker.patch("qdrant_client.QdrantClient") driver = QdrantVectorStoreDriver( url="http://some_url", port=8080, diff --git a/tests/unit/tasks/test_prompt_task.py b/tests/unit/tasks/test_prompt_task.py index bcef8bce1..3a02309d3 100644 --- a/tests/unit/tasks/test_prompt_task.py +++ b/tests/unit/tasks/test_prompt_task.py @@ -111,10 +111,14 @@ def test_input(self): [TextArtifact("foo"), ImageArtifact(b"image-data", format="png", width=100, height=100)] ) ) - assert isinstance(task.input, ListArtifact) assert task.input.value[0].value == "foo" assert isinstance(task.input.value[1], ImageArtifact) assert task.input.value[1].value == b"image-data" assert task.input.value[1].format == "png" assert task.input.value[1].width == 100 + + # default case + task = PromptTask({"default": "test"}) + + assert task.input.value == str({"default": "test"}) From de2315c655c173d5d9d6d55b7a65c1f5e171b70d Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Tue, 2 Jul 2024 19:35:14 -0500 Subject: [PATCH 34/87] Bump pydantic,urllib3,requests (#933) --- poetry.lock | 92 +++++++++++++++++++++++++------------------------- pyproject.toml | 2 +- 2 files changed, 47 insertions(+), 47 deletions(-) diff --git a/poetry.lock b/poetry.lock index 1d925d6a1..f169895cc 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4174,47 +4174,47 @@ files = [ [[package]] name = "pydantic" -version = "1.10.15" +version = "1.10.16" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22ed12ee588b1df028a2aa5d66f07bf8f8b4c8579c2e96d5a9c1f96b77f3bb55"}, - {file = "pydantic-1.10.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75279d3cac98186b6ebc2597b06bcbc7244744f6b0b44a23e4ef01e5683cc0d2"}, - {file = "pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50f1666a9940d3d68683c9d96e39640f709d7a72ff8702987dab1761036206bb"}, - {file = "pydantic-1.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82790d4753ee5d00739d6cb5cf56bceb186d9d6ce134aca3ba7befb1eedbc2c8"}, - {file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d207d5b87f6cbefbdb1198154292faee8017d7495a54ae58db06762004500d00"}, - {file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e49db944fad339b2ccb80128ffd3f8af076f9f287197a480bf1e4ca053a866f0"}, - {file = "pydantic-1.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:d3b5c4cbd0c9cb61bbbb19ce335e1f8ab87a811f6d589ed52b0254cf585d709c"}, - {file = "pydantic-1.10.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c3d5731a120752248844676bf92f25a12f6e45425e63ce22e0849297a093b5b0"}, - {file = "pydantic-1.10.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c365ad9c394f9eeffcb30a82f4246c0006417f03a7c0f8315d6211f25f7cb654"}, - {file = "pydantic-1.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3287e1614393119c67bd4404f46e33ae3be3ed4cd10360b48d0a4459f420c6a3"}, - {file = "pydantic-1.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be51dd2c8596b25fe43c0a4a59c2bee4f18d88efb8031188f9e7ddc6b469cf44"}, - {file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6a51a1dd4aa7b3f1317f65493a182d3cff708385327c1c82c81e4a9d6d65b2e4"}, - {file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4e316e54b5775d1eb59187f9290aeb38acf620e10f7fd2f776d97bb788199e53"}, - {file = "pydantic-1.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:0d142fa1b8f2f0ae11ddd5e3e317dcac060b951d605fda26ca9b234b92214986"}, - {file = "pydantic-1.10.15-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7ea210336b891f5ea334f8fc9f8f862b87acd5d4a0cbc9e3e208e7aa1775dabf"}, - {file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3453685ccd7140715e05f2193d64030101eaad26076fad4e246c1cc97e1bb30d"}, - {file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bea1f03b8d4e8e86702c918ccfd5d947ac268f0f0cc6ed71782e4b09353b26f"}, - {file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:005655cabc29081de8243126e036f2065bd7ea5b9dff95fde6d2c642d39755de"}, - {file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:af9850d98fc21e5bc24ea9e35dd80a29faf6462c608728a110c0a30b595e58b7"}, - {file = "pydantic-1.10.15-cp37-cp37m-win_amd64.whl", hash = "sha256:d31ee5b14a82c9afe2bd26aaa405293d4237d0591527d9129ce36e58f19f95c1"}, - {file = "pydantic-1.10.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5e09c19df304b8123938dc3c53d3d3be6ec74b9d7d0d80f4f4b5432ae16c2022"}, - {file = "pydantic-1.10.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7ac9237cd62947db00a0d16acf2f3e00d1ae9d3bd602b9c415f93e7a9fc10528"}, - {file = "pydantic-1.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:584f2d4c98ffec420e02305cf675857bae03c9d617fcfdc34946b1160213a948"}, - {file = "pydantic-1.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbc6989fad0c030bd70a0b6f626f98a862224bc2b1e36bfc531ea2facc0a340c"}, - {file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d573082c6ef99336f2cb5b667b781d2f776d4af311574fb53d908517ba523c22"}, - {file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6bd7030c9abc80134087d8b6e7aa957e43d35714daa116aced57269a445b8f7b"}, - {file = "pydantic-1.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:3350f527bb04138f8aff932dc828f154847fbdc7a1a44c240fbfff1b57f49a12"}, - {file = "pydantic-1.10.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:51d405b42f1b86703555797270e4970a9f9bd7953f3990142e69d1037f9d9e51"}, - {file = "pydantic-1.10.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a980a77c52723b0dc56640ced396b73a024d4b74f02bcb2d21dbbac1debbe9d0"}, - {file = "pydantic-1.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f1a1fb467d3f49e1708a3f632b11c69fccb4e748a325d5a491ddc7b5d22383"}, - {file = "pydantic-1.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:676ed48f2c5bbad835f1a8ed8a6d44c1cd5a21121116d2ac40bd1cd3619746ed"}, - {file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:92229f73400b80c13afcd050687f4d7e88de9234d74b27e6728aa689abcf58cc"}, - {file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2746189100c646682eff0bce95efa7d2e203420d8e1c613dc0c6b4c1d9c1fde4"}, - {file = "pydantic-1.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:394f08750bd8eaad714718812e7fab615f873b3cdd0b9d84e76e51ef3b50b6b7"}, - {file = "pydantic-1.10.15-py3-none-any.whl", hash = "sha256:28e552a060ba2740d0d2aabe35162652c1459a0b9069fe0db7f4ee0e18e74d58"}, - {file = "pydantic-1.10.15.tar.gz", hash = "sha256:ca832e124eda231a60a041da4f013e3ff24949d94a01154b137fc2f2a43c3ffb"}, + {file = "pydantic-1.10.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1a539ac40551b01a85e899829aa43ca8036707474af8d74b48be288d4d2d2846"}, + {file = "pydantic-1.10.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a4fcc7b0b8038dbda2dda642cff024032dfae24a7960cc58e57a39eb1949b9b"}, + {file = "pydantic-1.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4660dd697de1ae2d4305a85161312611f64d5360663a9ba026cd6ad9e3fe14c3"}, + {file = "pydantic-1.10.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:900a787c574f903a97d0bf52a43ff3b6cf4fa0119674bcfc0e5fd1056d388ad9"}, + {file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d30192a63e6d3334c3f0c0506dd6ae9f1dce7b2f8845518915291393a5707a22"}, + {file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:16cf23ed599ca5ca937e37ba50ab114e6b5c387eb43a6cc533701605ad1be611"}, + {file = "pydantic-1.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:8d23111f41d1e19334edd51438fd57933f3eee7d9d2fa8cc3f5eda515a272055"}, + {file = "pydantic-1.10.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef287b8d7fc0e86a8bd1f902c61aff6ba9479c50563242fe88ba39692e98e1e0"}, + {file = "pydantic-1.10.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b9ded699bfd3b3912d796ff388b0c607e6d35d41053d37aaf8fd6082c660de9a"}, + {file = "pydantic-1.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:daeb199814333e4426c5e86d7fb610f4e230289f28cab90eb4de27330bef93cf"}, + {file = "pydantic-1.10.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5973843f1fa99ec6c3ac8d1a8698ac9340b35e45cca6c3e5beb5c3bd1ef15de6"}, + {file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6b8a7788a8528a558828fe4a48783cafdcf2612d13c491594a8161dc721629c"}, + {file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8abaecf54dacc9d991dda93c3b880d41092a8924cde94eeb811d7d9ab55df7d8"}, + {file = "pydantic-1.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:ddc7b682fbd23f051edc419dc6977e11dd2dbdd0cef9d05f0e15d1387862d230"}, + {file = "pydantic-1.10.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:067c2b5539f7839653ad8c3d1fc2f1343338da8677b7b2172abf3cd3fdc8f719"}, + {file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d1fc943583c046ecad0ff5d6281ee571b64e11b5503d9595febdce54f38b290"}, + {file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18548b30ccebe71d380b0886cc44ea5d80afbcc155e3518792f13677ad06097d"}, + {file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4e92292f9580fc5ea517618580fac24e9f6dc5657196e977c194a8e50e14f5a9"}, + {file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5da8bc4bb4f85b8c97cc7f11141fddbbd29eb25e843672e5807e19cc3d7c1b7f"}, + {file = "pydantic-1.10.16-cp37-cp37m-win_amd64.whl", hash = "sha256:a04ee1ea34172b87707a6ecfcdb120d7656892206b7c4dbdb771a73e90179fcb"}, + {file = "pydantic-1.10.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4fa86469fd46e732242c7acb83282d33f83591a7e06f840481327d5bf6d96112"}, + {file = "pydantic-1.10.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:89c2783dc261726fe7a5ce1121bce29a2f7eb9b1e704c68df2b117604e3b346f"}, + {file = "pydantic-1.10.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78e59fa919fa7a192f423d190d8660c35dd444efa9216662273f36826765424b"}, + {file = "pydantic-1.10.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7e82a80068c77f4b074032e031e642530b6d45cb8121fc7c99faa31fb6c6b72"}, + {file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d82d5956cee27a30e26a5b88d00a6a2a15a4855e13c9baf50175976de0dc282c"}, + {file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b7b99424cc0970ff08deccb549b5a6ec1040c0b449eab91723e64df2bd8fdca"}, + {file = "pydantic-1.10.16-cp38-cp38-win_amd64.whl", hash = "sha256:d97a35e1ba59442775201657171f601a2879e63517a55862a51f8d67cdfc0017"}, + {file = "pydantic-1.10.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9d91f6866fd3e303c632207813ef6bc4d86055e21c5e5a0a311983a9ac5f0192"}, + {file = "pydantic-1.10.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8d3c71d14c8bd26d2350c081908dbf59d5a6a8f9596d9ef2b09cc1e61c8662b"}, + {file = "pydantic-1.10.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b73e6386b439b4881d79244e9fc1e32d1e31e8d784673f5d58a000550c94a6c0"}, + {file = "pydantic-1.10.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f039881fb2ef86f6de6eacce6e71701b47500355738367413ccc1550b2a69cf"}, + {file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3895ddb26f22bdddee7e49741486aa7b389258c6f6771943e87fc00eabd79134"}, + {file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55b945da2756b5cef93d792521ad0d457fdf2f69fd5a2d10a27513f5281717dd"}, + {file = "pydantic-1.10.16-cp39-cp39-win_amd64.whl", hash = "sha256:22dd265c77c3976a34be78409b128cb84629284dfd1b69d2fa1507a36f84dc8b"}, + {file = "pydantic-1.10.16-py3-none-any.whl", hash = "sha256:aa2774ba5412fd1c5cb890d08e8b0a3bb5765898913ba1f61a65a4810f03cf29"}, + {file = "pydantic-1.10.16.tar.gz", hash = "sha256:8bb388f6244809af69ee384900b10b677a69f1980fdc655ea419710cffcb5610"}, ] [package.dependencies] @@ -4912,13 +4912,13 @@ files = [ [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -6177,13 +6177,13 @@ files = [ [[package]] name = "urllib3" -version = "1.26.18" +version = "1.26.19" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, + {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, ] [package.extras] @@ -6553,4 +6553,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "d4a00633119a6b9616fc0ea31ae354f806d1fc363e4a930fa912d2d710aa8938" +content-hash = "a38d0f0671ff5deb42783721f4ce103e670a689f618e950451a807921f5d7139" diff --git a/pyproject.toml b/pyproject.toml index be33acb39..e4c84f624 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ numpy = ">=1" stringcase = "^1.2.0" docker = "^7.1.0" sqlalchemy = "~=1.0" -requests = "^2" +requests = "^2.32.0" # drivers cohere = { version = "^5.5.4", optional = true } From 89b69bcb5eca53b123e498374e86b7ec9f0aae4d Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Wed, 3 Jul 2024 07:45:05 -0700 Subject: [PATCH 35/87] Use custom discord invite link (#932) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f2a895ab..42df8fbd6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Checked with pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![codecov](https://codecov.io/github/griptape-ai/griptape/graph/badge.svg?token=HUBqUpl3NB)](https://codecov.io/github/griptape-ai/griptape) -[![Griptape Discord](https://dcbadge.vercel.app/api/server/gnWRz88eym?compact=true&style=flat)](https://discord.gg/gnWRz88eym) +[![Griptape Discord](https://dcbadge.vercel.app/api/server/gnWRz88eym?compact=true&style=flat)](https://discord.gg/griptape) Griptape is a modular Python framework for building AI-powered applications that securely connect to your enterprise data and APIs. It offers developers the ability to maintain control and flexibility at every step. From 1f09acb8089e054a2574f82ffce1b94b96603478 Mon Sep 17 00:00:00 2001 From: Vasily Vasinov Date: Wed, 3 Jul 2024 10:57:52 -0600 Subject: [PATCH 36/87] `RagContext` and other `RagEngine` improvements (#930) --- CHANGELOG.md | 17 +++--- docs/examples/talk-to-a-pdf.md | 17 +++--- docs/examples/talk-to-a-webpage.md | 18 +++--- .../griptape-framework/engines/rag-engines.md | 32 +++++----- .../structures/task-memory.md | 19 +++--- docs/griptape-framework/structures/tasks.md | 16 ++--- .../official-tools/rag-client.md | 16 ++--- griptape/engines/rag/modules/__init__.py | 36 +++++------ .../engines/rag/modules/base_rag_module.py | 15 ++++- .../metadata_generation_rag_module.py | 20 ------- .../modules/query/base_query_rag_module.py | 2 +- .../related_query_generation_rag_module.py | 34 ----------- .../{generation => response}/__init__.py | 0 .../base_after_response_rag_module.py} | 2 +- .../base_before_response_rag_module.py} | 2 +- .../base_response_rag_module.py} | 2 +- .../metadata_before_response_rag_module.py | 19 ++++++ .../prompt_response_rag_module.py} | 10 ++-- .../rulesets_before_response_rag_module.py} | 4 +- .../text_chunks_response_rag_module.py | 12 ++++ ...le.py => text_chunks_rerank_rag_module.py} | 4 +- .../retrieval/text_retrieval_rag_module.py | 36 ----------- .../vector_store_retrieval_rag_module.py | 24 ++++++++ griptape/engines/rag/rag_context.py | 16 ++--- griptape/engines/rag/rag_engine.py | 27 +++++++-- griptape/engines/rag/stages/__init__.py | 4 +- griptape/engines/rag/stages/base_rag_stage.py | 5 ++ .../rag/stages/generation_rag_stage.py | 33 ----------- .../engines/rag/stages/query_rag_stage.py | 17 +++--- .../engines/rag/stages/response_rag_stage.py | 46 +++++++++++++++ .../engines/rag/stages/retrieval_rag_stage.py | 13 +++- .../task/storage/base_artifact_storage.py | 2 +- .../task/storage/blob_artifact_storage.py | 2 +- .../task/storage/text_artifact_storage.py | 25 +++++++- griptape/memory/task/task_memory.py | 2 +- griptape/structures/structure.py | 23 ++++---- griptape/tasks/rag_task.py | 4 +- .../rag/modules/prompt_generation/system.j2 | 15 ----- .../rag/modules/query_generation/system.j2 | 3 - .../metadata}/system.j2 | 0 .../rag/modules/response/prompt/system.j2 | 19 ++++++ griptape/tools/base_tool.py | 6 +- griptape/tools/rag_client/tool.py | 4 +- griptape/tools/task_memory_client/tool.py | 4 +- tests/mocks/mock_rag_module.py | 4 ++ ...est_metadata_before_response_rag_module.py | 19 ++++++ .../test_metadata_generation_rag_module.py | 14 ----- ....py => test_prompt_response_rag_module.py} | 8 +-- ...est_rulesets_before_response_rag_module.py | 10 ++++ .../test_rulesets_generation_rag_module.py | 10 ---- .../test_text_chunks_response_rag_module.py | 15 +++++ ...est_related_query_generation_rag_module.py | 13 ---- ... => test_text_chunks_rerank_rag_module.py} | 8 +-- .../test_text_retrieval_rag_module.py | 20 ------- .../test_vector_store_retrieval_rag_module.py | 59 +++++++++++++++++++ .../rag/modules/test_base_rag_nodule.py | 27 +++++++++ tests/unit/engines/rag/test_rag_engine.py | 34 ++++++++--- tests/unit/structures/test_agent.py | 2 +- tests/unit/tasks/test_rag_task.py | 8 +-- tests/unit/tools/test_base_tool.py | 4 -- tests/utils/defaults.py | 9 +-- 61 files changed, 516 insertions(+), 375 deletions(-) delete mode 100644 griptape/engines/rag/modules/generation/metadata_generation_rag_module.py delete mode 100644 griptape/engines/rag/modules/query/related_query_generation_rag_module.py rename griptape/engines/rag/modules/{generation => response}/__init__.py (100%) rename griptape/engines/rag/modules/{generation/base_after_generation_rag_module.py => response/base_after_response_rag_module.py} (82%) rename griptape/engines/rag/modules/{generation/base_before_generation_rag_module.py => response/base_before_response_rag_module.py} (82%) rename griptape/engines/rag/modules/{generation/base_generation_rag_module.py => response/base_response_rag_module.py} (83%) create mode 100644 griptape/engines/rag/modules/response/metadata_before_response_rag_module.py rename griptape/engines/rag/modules/{generation/prompt_generation_rag_module.py => response/prompt_response_rag_module.py} (87%) rename griptape/engines/rag/modules/{generation/rulesets_generation_rag_module.py => response/rulesets_before_response_rag_module.py} (73%) create mode 100644 griptape/engines/rag/modules/response/text_chunks_response_rag_module.py rename griptape/engines/rag/modules/retrieval/{text_rerank_rag_module.py => text_chunks_rerank_rag_module.py} (69%) delete mode 100644 griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py delete mode 100644 griptape/engines/rag/stages/generation_rag_stage.py create mode 100644 griptape/engines/rag/stages/response_rag_stage.py delete mode 100644 griptape/templates/engines/rag/modules/prompt_generation/system.j2 delete mode 100644 griptape/templates/engines/rag/modules/query_generation/system.j2 rename griptape/templates/engines/rag/modules/{metadata_generation => response/metadata}/system.j2 (100%) create mode 100644 griptape/templates/engines/rag/modules/response/prompt/system.j2 create mode 100644 tests/mocks/mock_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py delete mode 100644 tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py rename tests/unit/engines/rag/modules/generation/{test_prompt_generation_rag_module.py => test_prompt_response_rag_module.py} (71%) create mode 100644 tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py delete mode 100644 tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py delete mode 100644 tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py rename tests/unit/engines/rag/modules/retrieval/{test_text_rerank_rag_module.py => test_text_chunks_rerank_rag_module.py} (62%) delete mode 100644 tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py create mode 100644 tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py create mode 100644 tests/unit/engines/rag/modules/test_base_rag_nodule.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 399da1969..91c8fe89f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,17 +38,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - RAG stages: - `QueryRagStage` for parsing and expanding queries. - `RetrievalRagStage` for retrieving content. - - `GenerationRagStage` for augmenting and generating outputs. + - `ResponseRagStage` for augmenting and generating outputs. - RAG modules: - - Query: - - `RelatedQueryGenerationRagModule` for generating related queries. - Retrieval: - - `TextRetrievalRagModule` for retrieving text chunks. - - `TextRerankRagModule` for re-ranking retrieved results. - - Generation: - - `MetadataGenerationRagModule` for appending metadata. - - `RulesetsGenerationRagModule` for appending rulesets. - - `PromptGenerationRagModule` for generating responses based on retrieved text chunks. + - `VectorStoreRetrievalRagModule` for retrieving text chunks from vector stores. + - `TextChunksRerankRagModule` for re-ranking retrieved results. + - Response: + - `MetadataBeforeResponseRagModule` for appending metadata. + - `RulesetsBeforeResponseRagModule` for appending rulesets. + - `PromptResponseRagModule` for generating responses based on retrieved text chunks. + - `TextChunksResponseRagModule` for responding with retrieved text chunks. - `RagClient` tool for exposing `RagEngines` to LLM agents. - `RagTask` task for including `RagEngines` in any structure. - Rerank drivers: diff --git a/docs/examples/talk-to-a-pdf.md b/docs/examples/talk-to-a-pdf.md index a39832961..a3f47f0c6 100644 --- a/docs/examples/talk-to-a-pdf.md +++ b/docs/examples/talk-to-a-pdf.md @@ -4,8 +4,8 @@ This example demonstrates how to vectorize a PDF of the [Attention Is All You Ne import requests from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.loaders import PdfLoader from griptape.structures import Agent from griptape.tools import RagClient @@ -19,15 +19,18 @@ vector_store = LocalVectorStoreDriver( engine = RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ - TextRetrievalRagModule( - namespace=namespace, + VectorStoreRetrievalRagModule( vector_store_driver=vector_store, - top_n=20 + query_params={ + "namespace": namespace, + "top_n": 20 + + } ) ] ), - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule( + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) diff --git a/docs/examples/talk-to-a-webpage.md b/docs/examples/talk-to-a-webpage.md index ddd1a18c9..d1d0da5fa 100644 --- a/docs/examples/talk-to-a-webpage.md +++ b/docs/examples/talk-to-a-webpage.md @@ -3,8 +3,8 @@ This example demonstrates how to vectorize a webpage and setup a Griptape agent ```python from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.loaders import WebLoader from griptape.rules import Ruleset, Rule from griptape.structures import Agent @@ -18,15 +18,18 @@ vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDri engine = RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ - TextRetrievalRagModule( - namespace=namespace, + VectorStoreRetrievalRagModule( vector_store_driver=vector_store_driver, - top_n=20 + query_params={ + "namespace": namespace, + "top_n": 20 + + } ) ] ), - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule( + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) @@ -40,7 +43,6 @@ vector_store_driver.upsert_text_artifacts( {namespace: artifacts} ) - vector_store_tool = RagClient( description="Contains information about physics. " "Use it to answer any physics-related questions.", diff --git a/docs/griptape-framework/engines/rag-engines.md b/docs/griptape-framework/engines/rag-engines.md index 600b91d03..c03bf0f47 100644 --- a/docs/griptape-framework/engines/rag-engines.md +++ b/docs/griptape-framework/engines/rag-engines.md @@ -10,21 +10,23 @@ ### RAG Stages - `QueryRagStage` is for parsing and expanding queries. - `RetrievalRagStage` is for retrieving content. -- `GenerationRagStage` is for augmenting and generating outputs. +- `ResponseRagStage` is for augmenting and generating outputs. ### RAG Modules #### Query -- `RelatedQueryGenerationRagModule` is for generating related queries. + +No modules implemented yet. #### Retrieval - `TextRetrievalRagModule` is for retrieving text chunks. -- `TextRerankRagModule` is for re-ranking retrieved results. +- `TextChunksRerankRagModule` is for re-ranking retrieved results. -#### Generation -- `MetadataGenerationRagModule` is for appending metadata. -- `RulesetsGenerationRagModule` is for appending rulesets. -- `PromptGenerationRagModule` is for generating responses based on retrieved text chunks. +#### Response +- `MetadataBeforeResponseRagModule` is for appending metadata. +- `RulesetsBeforeResponseRagModule` is for appending rulesets. +- `PromptResponseRagModule` is for generating responses based on retrieved text chunks. +- `TextChunksResponseRagModule` for responding with retrieved text chunks. ### Example @@ -32,8 +34,8 @@ from griptape.artifacts import TextArtifact from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage vector_store = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) @@ -46,15 +48,17 @@ vector_store.upsert_text_artifacts({"griptape": artifacts}) engine = RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ - TextRetrievalRagModule( - namespace="griptape", + VectorStoreRetrievalRagModule( vector_store_driver=vector_store, - top_n=20 + query_params={ + "namespace": "griptape", + "top_n": 20 + } ) ] ), - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule( + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) diff --git a/docs/griptape-framework/structures/task-memory.md b/docs/griptape-framework/structures/task-memory.md index 4597b6402..24f0c6363 100644 --- a/docs/griptape-framework/structures/task-memory.md +++ b/docs/griptape-framework/structures/task-memory.md @@ -208,14 +208,13 @@ from griptape.drivers import ( OpenAiChatPromptDriver, OpenAiEmbeddingDriver, ) from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.memory import TaskMemory from griptape.memory.task.storage import TextArtifactStorage from griptape.structures import Agent from griptape.tools import FileManager, TaskMemoryClient, WebScraper - vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) agent = Agent( @@ -228,19 +227,23 @@ agent = Agent( rag_engine=RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ - TextRetrievalRagModule( - namespace="griptape", + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, - top_n=20 + query_params={ + "namespace": "griptape", + "count": 20 + } ) ] ), - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule( + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) ), + retrieval_rag_module_name="VectorStoreRetrievalRagModule", vector_store_driver=vector_store_driver ) } diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index c385df6cd..b839b2910 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -386,8 +386,8 @@ from griptape.tasks import RagTask from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.artifacts import TextArtifact from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage # Initialize Embedding Driver and Vector Store Driver vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) @@ -406,15 +406,17 @@ agent.add_task( rag_engine=RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ - TextRetrievalRagModule( - namespace="griptape", + VectorStoreRetrievalRagModule( vector_store_driver=vector_store_driver, - top_n=20 + query_params={ + "namespace": "griptape", + "top_n": 20 + } ) ] ), - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule( + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) diff --git a/docs/griptape-tools/official-tools/rag-client.md b/docs/griptape-tools/official-tools/rag-client.md index 75bc5dee7..6c8f9f17d 100644 --- a/docs/griptape-tools/official-tools/rag-client.md +++ b/docs/griptape-tools/official-tools/rag-client.md @@ -8,8 +8,8 @@ from griptape.tasks import RagTask from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.artifacts import TextArtifact from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage # Initialize Embedding Driver and Vector Store Driver vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) @@ -28,15 +28,17 @@ agent.add_task( rag_engine=RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ - TextRetrievalRagModule( - namespace="griptape", + VectorStoreRetrievalRagModule( vector_store_driver=vector_store_driver, - top_n=20 + query_params={ + "namespace": "griptape", + "top_n": 20 + } ) ] ), - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule( + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) diff --git a/griptape/engines/rag/modules/__init__.py b/griptape/engines/rag/modules/__init__.py index a9550d8bb..cb11551e3 100644 --- a/griptape/engines/rag/modules/__init__.py +++ b/griptape/engines/rag/modules/__init__.py @@ -1,29 +1,29 @@ from .base_rag_module import BaseRagModule from .query.base_query_rag_module import BaseQueryRagModule -from .query.related_query_generation_rag_module import RelatedQueryGenerationRagModule from .retrieval.base_retrieval_rag_module import BaseRetrievalRagModule from .retrieval.base_rerank_rag_module import BaseRerankRagModule -from .retrieval.text_rerank_rag_module import TextRerankRagModule -from .retrieval.text_retrieval_rag_module import TextRetrievalRagModule -from .generation.base_before_generation_rag_module import BaseBeforeGenerationRagModule -from .generation.base_after_generation_rag_module import BaseAfterGenerationRagModule -from .generation.base_generation_rag_module import BaseGenerationRagModule -from .generation.prompt_generation_rag_module import PromptGenerationRagModule -from .generation.rulesets_generation_rag_module import RulesetsGenerationRagModule -from .generation.metadata_generation_rag_module import MetadataGenerationRagModule +from .retrieval.text_chunks_rerank_rag_module import TextChunksRerankRagModule +from .retrieval.vector_store_retrieval_rag_module import VectorStoreRetrievalRagModule +from .response.base_before_response_rag_module import BaseBeforeResponseRagModule +from .response.base_after_response_rag_module import BaseAfterResponseRagModule +from .response.base_response_rag_module import BaseResponseRagModule +from .response.prompt_response_rag_module import PromptResponseRagModule +from .response.rulesets_before_response_rag_module import RulesetsBeforeResponseRagModule +from .response.metadata_before_response_rag_module import MetadataBeforeResponseRagModule +from .response.text_chunks_response_rag_module import TextChunksResponseRagModule __all__ = [ "BaseRagModule", "BaseQueryRagModule", - "RelatedQueryGenerationRagModule", "BaseRetrievalRagModule", "BaseRerankRagModule", - "TextRerankRagModule", - "TextRetrievalRagModule", - "BaseBeforeGenerationRagModule", - "BaseAfterGenerationRagModule", - "BaseGenerationRagModule", - "PromptGenerationRagModule", - "RulesetsGenerationRagModule", - "MetadataGenerationRagModule", + "TextChunksRerankRagModule", + "VectorStoreRetrievalRagModule", + "BaseBeforeResponseRagModule", + "BaseAfterResponseRagModule", + "BaseResponseRagModule", + "PromptResponseRagModule", + "RulesetsBeforeResponseRagModule", + "MetadataBeforeResponseRagModule", + "TextChunksResponseRagModule", ] diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py index 13563970d..becd94d9e 100644 --- a/griptape/engines/rag/modules/base_rag_module.py +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -1,14 +1,14 @@ from abc import ABC from concurrent import futures -from typing import Callable - +from typing import Callable, Any, Optional from attrs import define, field, Factory - +from griptape.engines.rag import RagContext from griptape.common import PromptStack, Message @define(kw_only=True) class BaseRagModule(ABC): + name: str = field(default=Factory(lambda self: self.__class__.__name__, takes_self=True), kw_only=True) futures_executor_fn: Callable[[], futures.Executor] = field( default=Factory(lambda: lambda: futures.ThreadPoolExecutor()) ) @@ -17,3 +17,12 @@ def generate_query_prompt_stack(self, system_prompt: str, query: str) -> PromptS return PromptStack( messages=[Message(system_prompt, role=Message.SYSTEM_ROLE), Message(query, role=Message.USER_ROLE)] ) + + def get_context_param(self, context: RagContext, key: str) -> Optional[Any]: + return context.module_params.get(self.name, {}).get(key) + + def set_context_param(self, context: RagContext, key: str, value: Any) -> None: + if not isinstance(context.module_params.get(self.name), dict): + context.module_params[self.name] = {} + + context.module_params[self.name][key] = value diff --git a/griptape/engines/rag/modules/generation/metadata_generation_rag_module.py b/griptape/engines/rag/modules/generation/metadata_generation_rag_module.py deleted file mode 100644 index 1ce689960..000000000 --- a/griptape/engines/rag/modules/generation/metadata_generation_rag_module.py +++ /dev/null @@ -1,20 +0,0 @@ -from typing import Optional -from attrs import define, field -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseBeforeGenerationRagModule -from griptape.utils import J2 - - -@define(kw_only=True) -class MetadataGenerationRagModule(BaseBeforeGenerationRagModule): - metadata: Optional[str] = field(default=None) - - def run(self, context: RagContext) -> RagContext: - metadata = context.metadata if self.metadata is None else self.metadata - - if metadata is not None: - context.before_query.append( - J2("engines/rag/modules/metadata_generation/system.j2").render(metadata=metadata) - ) - - return context diff --git a/griptape/engines/rag/modules/query/base_query_rag_module.py b/griptape/engines/rag/modules/query/base_query_rag_module.py index c9eace864..195bba6bd 100644 --- a/griptape/engines/rag/modules/query/base_query_rag_module.py +++ b/griptape/engines/rag/modules/query/base_query_rag_module.py @@ -7,4 +7,4 @@ @define(kw_only=True) class BaseQueryRagModule(BaseRagModule, ABC): @abstractmethod - def run(self, context: RagContext) -> list[str]: ... + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/query/related_query_generation_rag_module.py b/griptape/engines/rag/modules/query/related_query_generation_rag_module.py deleted file mode 100644 index 138e5f034..000000000 --- a/griptape/engines/rag/modules/query/related_query_generation_rag_module.py +++ /dev/null @@ -1,34 +0,0 @@ -from typing import Callable -from attrs import define, field, Factory -from griptape import utils -from griptape.drivers import BasePromptDriver -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseQueryRagModule -from griptape.utils import J2 - - -@define(kw_only=True) -class RelatedQueryGenerationRagModule(BaseQueryRagModule): - query_count: int = field(default=5) - prompt_driver: BasePromptDriver = field() - generate_system_template: Callable[[str], str] = field( - default=Factory(lambda self: self.default_system_template_generator, takes_self=True), kw_only=True - ) - - def run(self, context: RagContext) -> list[str]: - system_prompt = self.generate_system_template(context.initial_query) - - with self.futures_executor_fn() as executor: - results = utils.execute_futures_list( - [ - executor.submit( - self.prompt_driver.run, self.generate_query_prompt_stack(system_prompt, "Alternative query: ") - ) - for _ in range(self.query_count) - ] - ) - - return [r.value for r in results] - - def default_system_template_generator(self, initial_query: str) -> str: - return J2("engines/rag/modules/query_generation/system.j2").render(initial_query=initial_query) diff --git a/griptape/engines/rag/modules/generation/__init__.py b/griptape/engines/rag/modules/response/__init__.py similarity index 100% rename from griptape/engines/rag/modules/generation/__init__.py rename to griptape/engines/rag/modules/response/__init__.py diff --git a/griptape/engines/rag/modules/generation/base_after_generation_rag_module.py b/griptape/engines/rag/modules/response/base_after_response_rag_module.py similarity index 82% rename from griptape/engines/rag/modules/generation/base_after_generation_rag_module.py rename to griptape/engines/rag/modules/response/base_after_response_rag_module.py index f3a26e9db..03d906204 100644 --- a/griptape/engines/rag/modules/generation/base_after_generation_rag_module.py +++ b/griptape/engines/rag/modules/response/base_after_response_rag_module.py @@ -5,6 +5,6 @@ @define(kw_only=True) -class BaseAfterGenerationRagModule(BaseRagModule, ABC): +class BaseAfterResponseRagModule(BaseRagModule, ABC): @abstractmethod def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/generation/base_before_generation_rag_module.py b/griptape/engines/rag/modules/response/base_before_response_rag_module.py similarity index 82% rename from griptape/engines/rag/modules/generation/base_before_generation_rag_module.py rename to griptape/engines/rag/modules/response/base_before_response_rag_module.py index 6a57bd6af..2a16b68d0 100644 --- a/griptape/engines/rag/modules/generation/base_before_generation_rag_module.py +++ b/griptape/engines/rag/modules/response/base_before_response_rag_module.py @@ -5,6 +5,6 @@ @define(kw_only=True) -class BaseBeforeGenerationRagModule(BaseRagModule, ABC): +class BaseBeforeResponseRagModule(BaseRagModule, ABC): @abstractmethod def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/generation/base_generation_rag_module.py b/griptape/engines/rag/modules/response/base_response_rag_module.py similarity index 83% rename from griptape/engines/rag/modules/generation/base_generation_rag_module.py rename to griptape/engines/rag/modules/response/base_response_rag_module.py index 08f1b5323..72a7dce1b 100644 --- a/griptape/engines/rag/modules/generation/base_generation_rag_module.py +++ b/griptape/engines/rag/modules/response/base_response_rag_module.py @@ -5,6 +5,6 @@ @define(kw_only=True) -class BaseGenerationRagModule(BaseRagModule, ABC): +class BaseResponseRagModule(BaseRagModule, ABC): @abstractmethod def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py new file mode 100644 index 000000000..7bd1cf0a9 --- /dev/null +++ b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py @@ -0,0 +1,19 @@ +from typing import Optional +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseBeforeResponseRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class MetadataBeforeResponseRagModule(BaseBeforeResponseRagModule): + metadata: Optional[str] = field(default=None) + + def run(self, context: RagContext) -> RagContext: + context_metadata = self.get_context_param(context, "metadata") + metadata = self.metadata if context_metadata is None else context_metadata + + if metadata is not None: + context.before_query.append(J2("engines/rag/modules/response/metadata/system.j2").render(metadata=metadata)) + + return context diff --git a/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py b/griptape/engines/rag/modules/response/prompt_response_rag_module.py similarity index 87% rename from griptape/engines/rag/modules/generation/prompt_generation_rag_module.py rename to griptape/engines/rag/modules/response/prompt_response_rag_module.py index 26d95bdd1..7b29de7ee 100644 --- a/griptape/engines/rag/modules/generation/prompt_generation_rag_module.py +++ b/griptape/engines/rag/modules/response/prompt_response_rag_module.py @@ -3,12 +3,12 @@ from griptape.artifacts.text_artifact import TextArtifact from griptape.drivers import BasePromptDriver from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseGenerationRagModule +from griptape.engines.rag.modules import BaseResponseRagModule from griptape.utils import J2 @define(kw_only=True) -class PromptGenerationRagModule(BaseGenerationRagModule): +class PromptResponseRagModule(BaseResponseRagModule): answer_token_offset: int = field(default=400) prompt_driver: BasePromptDriver = field() generate_system_template: Callable[[list[str], list[str], list[str]], str] = field( @@ -16,7 +16,7 @@ class PromptGenerationRagModule(BaseGenerationRagModule): ) def run(self, context: RagContext) -> RagContext: - query = context.initial_query + query = context.query before_query = context.before_query after_query = context.after_query text_artifact_chunks = context.text_chunks @@ -24,7 +24,7 @@ def run(self, context: RagContext) -> RagContext: if query: tokenizer = self.prompt_driver.tokenizer text_chunks = [] - system_prompt = "" + system_prompt = self.generate_system_template(text_chunks, before_query, after_query) for artifact in text_artifact_chunks: text_chunks.append(artifact.value) @@ -53,7 +53,7 @@ def run(self, context: RagContext) -> RagContext: def default_system_template_generator( self, text_chunks: list[str], before_system_prompt: list, after_system_prompt: list ) -> str: - return J2("engines/rag/modules/prompt_generation/system.j2").render( + return J2("engines/rag/modules/response/prompt/system.j2").render( text_chunks=text_chunks, before_system_prompt="\n\n".join(before_system_prompt), after_system_prompt="\n\n".join(after_system_prompt), diff --git a/griptape/engines/rag/modules/generation/rulesets_generation_rag_module.py b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py similarity index 73% rename from griptape/engines/rag/modules/generation/rulesets_generation_rag_module.py rename to griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py index ff29c379a..27a421c1b 100644 --- a/griptape/engines/rag/modules/generation/rulesets_generation_rag_module.py +++ b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py @@ -1,12 +1,12 @@ from attrs import define, field from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseBeforeGenerationRagModule +from griptape.engines.rag.modules import BaseBeforeResponseRagModule from griptape.rules import Ruleset from griptape.utils import J2 @define -class RulesetsGenerationRagModule(BaseBeforeGenerationRagModule): +class RulesetsBeforeResponseRagModule(BaseBeforeResponseRagModule): rulesets: list[Ruleset] = field(kw_only=True) def run(self, context: RagContext) -> RagContext: diff --git a/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py b/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py new file mode 100644 index 000000000..699aa1124 --- /dev/null +++ b/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py @@ -0,0 +1,12 @@ +from attrs import define +from griptape.artifacts import ListArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseResponseRagModule + + +@define(kw_only=True) +class TextChunksResponseRagModule(BaseResponseRagModule): + def run(self, context: RagContext) -> RagContext: + context.output = ListArtifact(context.text_chunks) + + return context diff --git a/griptape/engines/rag/modules/retrieval/text_rerank_rag_module.py b/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py similarity index 69% rename from griptape/engines/rag/modules/retrieval/text_rerank_rag_module.py rename to griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py index a766d0cb6..b78c3a880 100644 --- a/griptape/engines/rag/modules/retrieval/text_rerank_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py @@ -7,6 +7,6 @@ @define(kw_only=True) -class TextRerankRagModule(BaseRerankRagModule): +class TextChunksRerankRagModule(BaseRerankRagModule): def run(self, context: RagContext) -> Sequence[BaseArtifact]: - return self.rerank_driver.run(context.initial_query, context.text_chunks) + return self.rerank_driver.run(context.query, context.text_chunks) diff --git a/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py deleted file mode 100644 index 9c756bfea..000000000 --- a/griptape/engines/rag/modules/retrieval/text_retrieval_rag_module.py +++ /dev/null @@ -1,36 +0,0 @@ -from __future__ import annotations -import itertools -from typing import TYPE_CHECKING, Optional, Sequence -from attrs import define, field -from griptape import utils -from griptape.artifacts import TextArtifact -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseRetrievalRagModule - -if TYPE_CHECKING: - from griptape.drivers import BaseVectorStoreDriver - - -@define(kw_only=True) -class TextRetrievalRagModule(BaseRetrievalRagModule): - vector_store_driver: BaseVectorStoreDriver = field() - namespace: Optional[str] = field(default=None) - top_n: Optional[int] = field(default=None) - - def run(self, context: RagContext) -> Sequence[TextArtifact]: - all_queries = [context.initial_query] + context.alternative_queries - namespace = self.namespace or context.namespace - - with self.futures_executor_fn() as executor: - results = utils.execute_futures_list( - [ - executor.submit(self.vector_store_driver.query, query, self.top_n, namespace, False) - for query in all_queries - ] - ) - - return [ - artifact - for artifact in [r.to_artifact() for r in list(itertools.chain.from_iterable(results))] - if isinstance(artifact, TextArtifact) - ] diff --git a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py new file mode 100644 index 000000000..e91650faf --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py @@ -0,0 +1,24 @@ +from __future__ import annotations +from typing import TYPE_CHECKING, Sequence, Any, Callable +from attrs import define, field, Factory +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRetrievalRagModule + +if TYPE_CHECKING: + from griptape.drivers import BaseVectorStoreDriver + + +@define(kw_only=True) +class VectorStoreRetrievalRagModule(BaseRetrievalRagModule): + vector_store_driver: BaseVectorStoreDriver = field() + query_params: dict[str, Any] = field(factory=dict) + process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], Sequence[TextArtifact]] = field( + default=Factory(lambda: lambda es: [e.to_artifact() for e in es]) + ) + + def run(self, context: RagContext) -> Sequence[TextArtifact]: + context_query_params = self.get_context_param(context, "query_params") + query_params = self.query_params if context_query_params is None else context_query_params + + return self.process_query_output_fn(self.vector_store_driver.query(context.query, **query_params)) diff --git a/griptape/engines/rag/rag_context.py b/griptape/engines/rag/rag_context.py index 5f8ce9d6a..ce0d1adc6 100644 --- a/griptape/engines/rag/rag_context.py +++ b/griptape/engines/rag/rag_context.py @@ -1,6 +1,6 @@ from typing import Optional from attrs import define, field -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, BaseArtifact @define(kw_only=True) @@ -9,21 +9,17 @@ class RagContext: method. Attributes: - initial_query: Query provided by the user. - namespace: Optional namespace override for modules with an explicit namespace parameter. - metadata: Optional metadata override for modules with an explicit metadata parameter. - alternative_queries: Optional queries to expand retrieval results. + query: Query provided by the user. + module_params: Dictionary of dictionary parameters to be used by modules. First key should be the module name and the second a parameter name. before_query: An optional list of strings to add before the query in generation modules. after_query: An optional list of strings to add after the query in generation modules. text_chunks: A list of text chunks to pass around from the retrieval stage to the generation stage. output: Final output from the generation stage. """ - initial_query: str = field() - namespace: Optional[str] = field(default=None) - metadata: Optional[str] = field(default=None) - alternative_queries: list[str] = field(factory=list) + query: str = field() + module_params: dict[str, dict] = field(factory=dict) before_query: list[str] = field(factory=list) after_query: list[str] = field(factory=list) text_chunks: list[TextArtifact] = field(factory=list) - output: Optional[TextArtifact] = field(default=None) + output: Optional[BaseArtifact] = field(default=None) diff --git a/griptape/engines/rag/rag_engine.py b/griptape/engines/rag/rag_engine.py index 1c2176128..da8a2eebe 100644 --- a/griptape/engines/rag/rag_engine.py +++ b/griptape/engines/rag/rag_engine.py @@ -1,17 +1,34 @@ from typing import Optional from attrs import define, field from griptape.engines.rag import RagContext -from griptape.engines.rag.stages import QueryRagStage, GenerationRagStage, RetrievalRagStage +from griptape.engines.rag.stages import QueryRagStage, ResponseRagStage, RetrievalRagStage @define(kw_only=True) class RagEngine: query_stage: Optional[QueryRagStage] = field(default=None) retrieval_stage: Optional[RetrievalRagStage] = field(default=None) - generation_stage: Optional[GenerationRagStage] = field(default=None) + response_stage: Optional[ResponseRagStage] = field(default=None) + + def __attrs_post_init__(self) -> None: + modules = [] + + if self.query_stage is not None: + modules.extend(self.query_stage.modules) + + if self.retrieval_stage is not None: + modules.extend(self.retrieval_stage.modules) + + if self.response_stage is not None: + modules.extend(self.response_stage.modules) + + module_names = [m.name for m in modules] + + if len(module_names) > len(set(module_names)): + raise ValueError("module names have to be unique") def process_query(self, query: str) -> RagContext: - return self.process(RagContext(initial_query=query)) + return self.process(RagContext(query=query)) def process(self, context: RagContext) -> RagContext: if self.query_stage: @@ -20,7 +37,7 @@ def process(self, context: RagContext) -> RagContext: if self.retrieval_stage: context = self.retrieval_stage.run(context) - if self.generation_stage: - context = self.generation_stage.run(context) + if self.response_stage: + context = self.response_stage.run(context) return context diff --git a/griptape/engines/rag/stages/__init__.py b/griptape/engines/rag/stages/__init__.py index 85a603d03..14756563c 100644 --- a/griptape/engines/rag/stages/__init__.py +++ b/griptape/engines/rag/stages/__init__.py @@ -1,6 +1,6 @@ from .base_rag_stage import BaseRagStage from .retrieval_rag_stage import RetrievalRagStage from .query_rag_stage import QueryRagStage -from .generation_rag_stage import GenerationRagStage +from .response_rag_stage import ResponseRagStage -__all__ = ["BaseRagStage", "RetrievalRagStage", "QueryRagStage", "GenerationRagStage"] +__all__ = ["BaseRagStage", "RetrievalRagStage", "QueryRagStage", "ResponseRagStage"] diff --git a/griptape/engines/rag/stages/base_rag_stage.py b/griptape/engines/rag/stages/base_rag_stage.py index ca19e1bb4..4db996e30 100644 --- a/griptape/engines/rag/stages/base_rag_stage.py +++ b/griptape/engines/rag/stages/base_rag_stage.py @@ -3,6 +3,7 @@ from typing import Callable from attrs import define, field, Factory from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule @define(kw_only=True) @@ -13,3 +14,7 @@ class BaseRagStage(ABC): @abstractmethod def run(self, context: RagContext) -> RagContext: ... + + @property + @abstractmethod + def modules(self) -> list[BaseRagModule]: ... diff --git a/griptape/engines/rag/stages/generation_rag_stage.py b/griptape/engines/rag/stages/generation_rag_stage.py deleted file mode 100644 index 60102889a..000000000 --- a/griptape/engines/rag/stages/generation_rag_stage.py +++ /dev/null @@ -1,33 +0,0 @@ -import logging -from attrs import define, field -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import ( - BaseGenerationRagModule, - BaseBeforeGenerationRagModule, - BaseAfterGenerationRagModule, -) -from griptape.engines.rag.stages import BaseRagStage - - -@define(kw_only=True) -class GenerationRagStage(BaseRagStage): - before_generator_modules: list[BaseBeforeGenerationRagModule] = field(factory=list) - generation_module: BaseGenerationRagModule = field() - after_generator_modules: list[BaseAfterGenerationRagModule] = field(factory=list) - - def run(self, context: RagContext) -> RagContext: - logging.info(f"GenerationStage: running {len(self.before_generator_modules)} before modules sequentially") - - for generator in self.before_generator_modules: - context = generator.run(context) - - logging.info("GenerationStage: running generation module") - - context = self.generation_module.run(context) - - logging.info(f"GenerationStage: running {len(self.after_generator_modules)} after modules sequentially") - - for generator in self.after_generator_modules: - context = generator.run(context) - - return context diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py index c2216aea8..84c200bc8 100644 --- a/griptape/engines/rag/stages/query_rag_stage.py +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -1,24 +1,23 @@ -import itertools import logging from attrs import define, field from griptape import utils from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseQueryRagModule +from griptape.engines.rag.modules import BaseQueryRagModule, BaseRagModule from griptape.engines.rag.stages import BaseRagStage @define(kw_only=True) class QueryRagStage(BaseRagStage): - query_generation_modules: list[BaseQueryRagModule] = field() + query_modules: list[BaseQueryRagModule] = field() + + @property + def modules(self) -> list[BaseRagModule]: + return self.query_modules # pyright: ignore def run(self, context: RagContext) -> RagContext: - logging.info(f"QueryStage: running {len(self.query_generation_modules)} query generation modules in parallel") + logging.info(f"QueryStage: running {len(self.query_modules)} query generation modules in parallel") with self.futures_executor_fn() as executor: - results = utils.execute_futures_list( - [executor.submit(r.run, context) for r in self.query_generation_modules] - ) - - context.alternative_queries = list(itertools.chain.from_iterable(results)) + utils.execute_futures_list([executor.submit(r.run, context) for r in self.query_modules]) return context diff --git a/griptape/engines/rag/stages/response_rag_stage.py b/griptape/engines/rag/stages/response_rag_stage.py new file mode 100644 index 000000000..aa0a15dfc --- /dev/null +++ b/griptape/engines/rag/stages/response_rag_stage.py @@ -0,0 +1,46 @@ +import logging +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import ( + BaseResponseRagModule, + BaseBeforeResponseRagModule, + BaseAfterResponseRagModule, + BaseRagModule, +) +from griptape.engines.rag.stages import BaseRagStage + + +@define(kw_only=True) +class ResponseRagStage(BaseRagStage): + before_response_modules: list[BaseBeforeResponseRagModule] = field(factory=list) + response_module: BaseResponseRagModule = field() + after_response_modules: list[BaseAfterResponseRagModule] = field(factory=list) + + @property + def modules(self) -> list[BaseRagModule]: + ms = [] + + ms.extend(self.before_response_modules) + ms.extend(self.after_response_modules) + + if self.response_module is not None: + ms.append(self.response_module) + + return ms + + def run(self, context: RagContext) -> RagContext: + logging.info(f"GenerationStage: running {len(self.before_response_modules)} before modules sequentially") + + for generator in self.before_response_modules: + context = generator.run(context) + + logging.info("GenerationStage: running generation module") + + context = self.response_module.run(context) + + logging.info(f"GenerationStage: running {len(self.after_response_modules)} after modules sequentially") + + for generator in self.after_response_modules: + context = generator.run(context) + + return context diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py index cbc90a43e..8fe376cd1 100644 --- a/griptape/engines/rag/stages/retrieval_rag_stage.py +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -5,7 +5,7 @@ from griptape import utils from griptape.artifacts import TextArtifact from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseRerankRagModule +from griptape.engines.rag.modules import BaseRerankRagModule, BaseRagModule from griptape.engines.rag.modules import BaseRetrievalRagModule from griptape.engines.rag.stages import BaseRagStage @@ -16,6 +16,17 @@ class RetrievalRagStage(BaseRagStage): rerank_module: Optional[BaseRerankRagModule] = field(default=None) max_chunks: Optional[int] = field(default=None) + @property + def modules(self) -> list[BaseRagModule]: + ms = [] + + ms.extend(self.retrieval_modules) + + if self.rerank_module is not None: + ms.append(self.rerank_module) + + return ms + def run(self, context: RagContext) -> RagContext: logging.info(f"RetrievalStage: running {len(self.retrieval_modules)} retrieval modules in parallel") diff --git a/griptape/memory/task/storage/base_artifact_storage.py b/griptape/memory/task/storage/base_artifact_storage.py index fbd226363..e8378fee4 100644 --- a/griptape/memory/task/storage/base_artifact_storage.py +++ b/griptape/memory/task/storage/base_artifact_storage.py @@ -20,4 +20,4 @@ def can_store(self, artifact: BaseArtifact) -> bool: ... def summarize(self, namespace: str) -> TextArtifact | InfoArtifact: ... @abstractmethod - def query(self, namespace: str, query: str, metadata: Any = None) -> TextArtifact | InfoArtifact: ... + def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifact: ... diff --git a/griptape/memory/task/storage/blob_artifact_storage.py b/griptape/memory/task/storage/blob_artifact_storage.py index 79b5798df..9d09e17fa 100644 --- a/griptape/memory/task/storage/blob_artifact_storage.py +++ b/griptape/memory/task/storage/blob_artifact_storage.py @@ -26,5 +26,5 @@ def load_artifacts(self, namespace: str) -> ListArtifact: def summarize(self, namespace: str) -> InfoArtifact: return InfoArtifact("can't summarize artifacts") - def query(self, namespace: str, query: str, metadata: Any = None) -> InfoArtifact: + def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifact: return InfoArtifact("can't query artifacts") diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 34d65a0c5..976a9ea5b 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -14,10 +14,16 @@ class TextArtifactStorage(BaseArtifactStorage): vector_store_driver: BaseVectorStoreDriver = field() rag_engine: Optional[RagEngine] = field(default=None) + retrieval_rag_module_name: Optional[str] = field(default=None) summary_engine: Optional[BaseSummaryEngine] = field(default=None) csv_extraction_engine: Optional[CsvExtractionEngine] = field(default=None) json_extraction_engine: Optional[JsonExtractionEngine] = field(default=None) + @rag_engine.validator # pyright: ignore + def validate_rag_engine(self, _, rag_engine: str) -> None: + if rag_engine is not None and self.retrieval_rag_module_name is None: + raise ValueError("You have to set retrieval_rag_module_name if rag_engine is provided") + def can_store(self, artifact: BaseArtifact) -> bool: return isinstance(artifact, TextArtifact) @@ -36,12 +42,25 @@ def summarize(self, namespace: str) -> TextArtifact: return self.summary_engine.summarize_artifacts(self.load_artifacts(namespace)) - def query(self, namespace: str, query: str, metadata: Any = None) -> TextArtifact | InfoArtifact: + def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifact: if self.rag_engine is None: - raise ValueError("RAG engine is not set.") + raise ValueError("rag_engine is not set") + + if self.retrieval_rag_module_name is None: + raise ValueError("retrieval_rag_module_name is not set") result = self.rag_engine.process( - RagContext(initial_query=query, namespace=namespace, metadata=None if metadata is None else str(metadata)) + RagContext( + query=query, + module_params={ + self.retrieval_rag_module_name: { + "query_params": { + "namespace": namespace, + "metadata": None if metadata is None else str(metadata), + } + } + }, + ) ).output if result is None: diff --git a/griptape/memory/task/task_memory.py b/griptape/memory/task/task_memory.py index 2f1fdbe16..df9c9be30 100644 --- a/griptape/memory/task/task_memory.py +++ b/griptape/memory/task/task_memory.py @@ -124,7 +124,7 @@ def summarize_namespace(self, namespace: str) -> TextArtifact | InfoArtifact: else: return InfoArtifact("Can't find memory content") - def query_namespace(self, namespace: str, query: str) -> TextArtifact | InfoArtifact: + def query_namespace(self, namespace: str, query: str) -> BaseArtifact: storage = self.namespace_storage.get(namespace) if storage: diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index c5854ccac..18e7d1284 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -13,12 +13,12 @@ from griptape.engines import CsvExtractionEngine, JsonExtractionEngine, PromptSummaryEngine from griptape.engines.rag import RagEngine from griptape.engines.rag.modules import ( - TextRetrievalRagModule, - RulesetsGenerationRagModule, - PromptGenerationRagModule, - MetadataGenerationRagModule, + VectorStoreRetrievalRagModule, + RulesetsBeforeResponseRagModule, + PromptResponseRagModule, + MetadataBeforeResponseRagModule, ) -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.events import BaseEvent, EventListener from griptape.events.finish_structure_run_event import FinishStructureRunEvent from griptape.events.start_structure_run_event import StartStructureRunEvent @@ -174,14 +174,14 @@ def default_config(self) -> BaseStructureConfig: def default_rag_engine(self) -> RagEngine: return RagEngine( retrieval_stage=RetrievalRagStage( - retrieval_modules=[TextRetrievalRagModule(vector_store_driver=self.config.vector_store_driver)] + retrieval_modules=[VectorStoreRetrievalRagModule(vector_store_driver=self.config.vector_store_driver)] ), - generation_stage=GenerationRagStage( - before_generator_modules=[ - RulesetsGenerationRagModule(rulesets=self.rulesets), - MetadataGenerationRagModule(), + response_stage=ResponseRagStage( + before_response_modules=[ + RulesetsBeforeResponseRagModule(rulesets=self.rulesets), + MetadataBeforeResponseRagModule(), ], - generation_module=PromptGenerationRagModule(prompt_driver=self.config.prompt_driver), + response_module=PromptResponseRagModule(prompt_driver=self.config.prompt_driver), ), ) @@ -191,6 +191,7 @@ def default_task_memory(self) -> TaskMemory: artifact_storages={ TextArtifact: TextArtifactStorage( rag_engine=self.rag_engine, + retrieval_rag_module_name="VectorStoreRetrievalRagModule", vector_store_driver=self.config.vector_store_driver, summary_engine=PromptSummaryEngine(prompt_driver=self.config.prompt_driver), csv_extraction_engine=CsvExtractionEngine(prompt_driver=self.config.prompt_driver), diff --git a/griptape/tasks/rag_task.py b/griptape/tasks/rag_task.py index d50e881c1..e85c8f28a 100644 --- a/griptape/tasks/rag_task.py +++ b/griptape/tasks/rag_task.py @@ -1,6 +1,6 @@ from __future__ import annotations from attrs import define, field -from griptape.artifacts import TextArtifact, ErrorArtifact +from griptape.artifacts import ErrorArtifact, BaseArtifact from griptape.engines.rag import RagEngine from griptape.tasks import BaseTextInputTask @@ -22,7 +22,7 @@ def rag_engine(self) -> RagEngine: def rag_engine(self, value: RagEngine) -> None: self._rag_engine = value - def run(self) -> TextArtifact | ErrorArtifact: + def run(self) -> BaseArtifact: result = self.rag_engine.process_query(self.input.to_text()).output if result is None: diff --git a/griptape/templates/engines/rag/modules/prompt_generation/system.j2 b/griptape/templates/engines/rag/modules/prompt_generation/system.j2 deleted file mode 100644 index 85c1b9fa8..000000000 --- a/griptape/templates/engines/rag/modules/prompt_generation/system.j2 +++ /dev/null @@ -1,15 +0,0 @@ -{% if before_system_prompt %} -{{ before_system_prompt }} - -{% endif %} -You can answer questions by searching through text chunks. Always be truthful. Don't make up facts. Use the below list of text chunks to respond. If the answer cannot be found in the chunks, say "I could not find an answer." - -{% for chunk in text_chunks %} -Text chunk: """ -{{ chunk }} -""" -{% endfor %} -{% if after_system_prompt %} - -{{ after_system_prompt }} -{% endif %} \ No newline at end of file diff --git a/griptape/templates/engines/rag/modules/query_generation/system.j2 b/griptape/templates/engines/rag/modules/query_generation/system.j2 deleted file mode 100644 index dd2a8e4bd..000000000 --- a/griptape/templates/engines/rag/modules/query_generation/system.j2 +++ /dev/null @@ -1,3 +0,0 @@ -Given the following query, generate an alternative query that has the same meaning but uses different words and introduces other related terms. Don't say anything else. Only output an alternative query and nothing else. - -Query: {{ initial_query }} \ No newline at end of file diff --git a/griptape/templates/engines/rag/modules/metadata_generation/system.j2 b/griptape/templates/engines/rag/modules/response/metadata/system.j2 similarity index 100% rename from griptape/templates/engines/rag/modules/metadata_generation/system.j2 rename to griptape/templates/engines/rag/modules/response/metadata/system.j2 diff --git a/griptape/templates/engines/rag/modules/response/prompt/system.j2 b/griptape/templates/engines/rag/modules/response/prompt/system.j2 new file mode 100644 index 000000000..4b06f3e8c --- /dev/null +++ b/griptape/templates/engines/rag/modules/response/prompt/system.j2 @@ -0,0 +1,19 @@ +{% if before_system_prompt %} +{{ before_system_prompt }} + +{% endif %} +Always be truthful. Don't make up facts. You can answer questions by searching through text chunks. Use the following list of text chunks to respond. If there are no text chunks available or text chunks don't have relevant information respond with "I could not find an answer." + +{% if text_chunks and text_chunks|length > 0 %} +{% for chunk in text_chunks %} +Text chunk: """ +{{ chunk }} +""" +{% endfor %} +{% if after_system_prompt %} + +{{ after_system_prompt }} +{% endif %} +{% else %} +No text chunks available. +{% endif %} \ No newline at end of file diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 8a0a924ac..03aaf22b5 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -35,7 +35,7 @@ class BaseTool(ActivityMixin, ABC): MANIFEST_FILE = "manifest.yml" REQUIREMENTS_FILE = "requirements.txt" - name: str = field(default=Factory(lambda self: self.class_name, takes_self=True), kw_only=True) + name: str = field(default=Factory(lambda self: self.__class__.__name__, takes_self=True), kw_only=True) input_memory: Optional[list[TaskMemory]] = field(default=None, kw_only=True) output_memory: Optional[dict[str, list[TaskMemory]]] = field(default=None, kw_only=True) install_dependencies_on_init: bool = field(default=True, kw_only=True) @@ -61,10 +61,6 @@ def validate_output_memory(self, _, output_memory: dict[str, Optional[list[TaskM if len(output_memory_names) > len(set(output_memory_names)): raise ValueError(f"memory names have to be unique in activity '{activity_name}' output") - @property - def class_name(self): - return self.__class__.__name__ - @property def manifest_path(self) -> str: return os.path.join(self.abs_dir_path, self.MANIFEST_FILE) diff --git a/griptape/tools/rag_client/tool.py b/griptape/tools/rag_client/tool.py index 78d716008..94422cc15 100644 --- a/griptape/tools/rag_client/tool.py +++ b/griptape/tools/rag_client/tool.py @@ -1,7 +1,7 @@ from __future__ import annotations from attrs import define, field from schema import Schema, Literal -from griptape.artifacts import ErrorArtifact, TextArtifact +from griptape.artifacts import ErrorArtifact, BaseArtifact from griptape.engines.rag import RagEngine from griptape.tools import BaseTool from griptape.utils.decorators import activity @@ -24,7 +24,7 @@ class RagClient(BaseTool): "schema": Schema({Literal("query", description="A natural language search query"): str}), } ) - def search(self, params: dict) -> TextArtifact | ErrorArtifact: + def search(self, params: dict) -> BaseArtifact: query = params["values"]["query"] try: diff --git a/griptape/tools/task_memory_client/tool.py b/griptape/tools/task_memory_client/tool.py index b60c0acc0..ce89da22e 100644 --- a/griptape/tools/task_memory_client/tool.py +++ b/griptape/tools/task_memory_client/tool.py @@ -1,7 +1,7 @@ from __future__ import annotations from attrs import define from schema import Schema, Literal -from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact +from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact, BaseArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity @@ -39,7 +39,7 @@ def summarize(self, params: dict) -> TextArtifact | InfoArtifact | ErrorArtifact ), } ) - def query(self, params: dict) -> TextArtifact | InfoArtifact | ErrorArtifact: + def query(self, params: dict) -> BaseArtifact: memory = self.find_input_memory(params["values"]["memory_name"]) artifact_namespace = params["values"]["artifact_namespace"] query = params["values"]["query"] diff --git a/tests/mocks/mock_rag_module.py b/tests/mocks/mock_rag_module.py new file mode 100644 index 000000000..98b69cee8 --- /dev/null +++ b/tests/mocks/mock_rag_module.py @@ -0,0 +1,4 @@ +from griptape.engines.rag.modules import BaseRagModule + + +class MockRagModule(BaseRagModule): ... diff --git a/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py new file mode 100644 index 000000000..43927bd8a --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py @@ -0,0 +1,19 @@ +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import MetadataBeforeResponseRagModule + + +class TestMetadataBeforeResponseRagModule: + def test_run(self): + module = MetadataBeforeResponseRagModule(name="foo") + + assert "foo" in module.run(RagContext(module_params={"foo": {"metadata": "foo"}}, query="test")).before_query[0] + + def test_run_with_override(self): + module = MetadataBeforeResponseRagModule(name="foo", metadata="bar") + + assert ( + "bar" + in module.run( + RagContext(module_params={"foo": {"query_params": {"metadata": "foo"}}}, query="test") + ).before_query[0] + ) diff --git a/tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py b/tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py deleted file mode 100644 index 0bd9f1f85..000000000 --- a/tests/unit/engines/rag/modules/generation/test_metadata_generation_rag_module.py +++ /dev/null @@ -1,14 +0,0 @@ -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import MetadataGenerationRagModule - - -class TestMetadataGenerationModule: - def test_run(self): - module = MetadataGenerationRagModule() - - assert "foo" in module.run(RagContext(metadata="foo", initial_query="test")).before_query[0] - - def test_run_with_override(self): - module = MetadataGenerationRagModule(metadata="bar") - - assert "bar" in module.run(RagContext(metadata="foo", initial_query="test")).before_query[0] diff --git a/tests/unit/engines/rag/modules/generation/test_prompt_generation_rag_module.py b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py similarity index 71% rename from tests/unit/engines/rag/modules/generation/test_prompt_generation_rag_module.py rename to tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py index 0227e2783..d8835bbe4 100644 --- a/tests/unit/engines/rag/modules/generation/test_prompt_generation_rag_module.py +++ b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py @@ -1,16 +1,16 @@ import pytest from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import PromptGenerationRagModule +from griptape.engines.rag.modules import PromptResponseRagModule from tests.mocks.mock_prompt_driver import MockPromptDriver -class TestPromptGenerationRagModule: +class TestPromptResponseRagModule: @pytest.fixture def module(self): - return PromptGenerationRagModule(prompt_driver=MockPromptDriver()) + return PromptResponseRagModule(prompt_driver=MockPromptDriver()) def test_run(self, module): - assert module.run(RagContext(initial_query="test")).output.value == "mock output" + assert module.run(RagContext(query="test")).output.value == "mock output" def test_prompt(self, module): system_message = module.default_system_template_generator( diff --git a/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py new file mode 100644 index 000000000..2750257f4 --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py @@ -0,0 +1,10 @@ +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import RulesetsBeforeResponseRagModule +from griptape.rules import Ruleset, Rule + + +class TestRulesetsBeforeResponseRagModule: + def test_run(self): + module = RulesetsBeforeResponseRagModule(rulesets=[Ruleset(name="test ruleset", rules=[Rule("test rule")])]) + + assert "test rule" in module.run(RagContext(query="test")).before_query[0] diff --git a/tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py b/tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py deleted file mode 100644 index 6e0fe725a..000000000 --- a/tests/unit/engines/rag/modules/generation/test_rulesets_generation_rag_module.py +++ /dev/null @@ -1,10 +0,0 @@ -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import RulesetsGenerationRagModule -from griptape.rules import Ruleset, Rule - - -class TestRulesetsGenerationRagModule: - def test_run(self): - module = RulesetsGenerationRagModule(rulesets=[Ruleset(name="test ruleset", rules=[Rule("test rule")])]) - - assert "test rule" in module.run(RagContext(initial_query="test")).before_query[0] diff --git a/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py new file mode 100644 index 000000000..6488d650e --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py @@ -0,0 +1,15 @@ +import pytest +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import TextChunksResponseRagModule + + +class TestTextChunksResponseRagModule: + @pytest.fixture + def module(self): + return TextChunksResponseRagModule() + + def test_run(self, module): + text_chunks = [TextArtifact("foo"), TextArtifact("bar")] + + assert module.run(RagContext(query="test", text_chunks=text_chunks)).output.value == text_chunks diff --git a/tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py b/tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py deleted file mode 100644 index 699d73de5..000000000 --- a/tests/unit/engines/rag/modules/query/test_related_query_generation_rag_module.py +++ /dev/null @@ -1,13 +0,0 @@ -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import RelatedQueryGenerationRagModule -from tests.mocks.mock_prompt_driver import MockPromptDriver - - -class TestRelatedQueryGenerationRagModule: - def test_run(self): - result = RelatedQueryGenerationRagModule(prompt_driver=MockPromptDriver(), query_count=10).run( - RagContext(initial_query="test") - ) - - assert len(result) == 10 - assert all(r == "mock output" for r in result) diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_rerank_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py similarity index 62% rename from tests/unit/engines/rag/modules/retrieval/test_text_rerank_rag_module.py rename to tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py index dc3e46a0a..838f02e37 100644 --- a/tests/unit/engines/rag/modules/retrieval/test_text_rerank_rag_module.py +++ b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py @@ -2,10 +2,10 @@ import pytest from griptape.drivers import CohereRerankDriver from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import TextRerankRagModule +from griptape.engines.rag.modules import TextChunksRerankRagModule -class TestTextRerankRagModule: +class TestTextChunksRerankRagModule: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value @@ -14,7 +14,7 @@ def mock_client(self, mocker): return mock_client def test_run(self, mock_client): - module = TextRerankRagModule(rerank_driver=CohereRerankDriver(api_key="api-key")) - result = module.run(RagContext(initial_query="test")) + module = TextChunksRerankRagModule(rerank_driver=CohereRerankDriver(api_key="api-key")) + result = module.run(RagContext(query="test")) assert len(result) == 2 diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py deleted file mode 100644 index 5b69012d1..000000000 --- a/tests/unit/engines/rag/modules/retrieval/test_text_retrieval_rag_module.py +++ /dev/null @@ -1,20 +0,0 @@ -from griptape.artifacts import TextArtifact -from griptape.drivers import LocalVectorStoreDriver -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import TextRetrievalRagModule -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver - - -class TestTextRetrievalRagModule: - def test_run(self): - vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) - module = TextRetrievalRagModule(vector_store_driver=vector_store_driver) - - vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") - vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") - - result = module.run(RagContext(initial_query="test")) - - assert len(result) == 2 - assert result[0].value == "foobar1" - assert result[1].value == "foobar2" diff --git a/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py new file mode 100644 index 000000000..3a01b3eaa --- /dev/null +++ b/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py @@ -0,0 +1,59 @@ +from griptape.artifacts import TextArtifact +from griptape.drivers import LocalVectorStoreDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver + + +class TestVectorStoreRetrievalRagModule: + def test_run_without_namespace(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + module = VectorStoreRetrievalRagModule(vector_store_driver=vector_store_driver) + + vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") + vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") + + result = module.run(RagContext(query="test")) + + assert len(result) == 2 + assert result[0].value == "foobar1" + assert result[1].value == "foobar2" + + def test_run_with_namespace(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + module = VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, query_params={"namespace": "test"} + ) + + vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") + vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") + + result = module.run(RagContext(query="test")) + + assert len(result) == 2 + assert result[0].value == "foobar1" + assert result[1].value == "foobar2" + + def test_run_with_namespace_overrides(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + module = VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, query_params={"namespace": "test"} + ) + + vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") + vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") + + result1 = module.run( + RagContext( + query="test", module_params={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "empty"}}} + ) + ) + + result2 = module.run( + RagContext( + query="test", module_params={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "test"}}} + ) + ) + + assert len(result1) == 0 + assert len(result2) == 2 diff --git a/tests/unit/engines/rag/modules/test_base_rag_nodule.py b/tests/unit/engines/rag/modules/test_base_rag_nodule.py new file mode 100644 index 000000000..0fc415e0e --- /dev/null +++ b/tests/unit/engines/rag/modules/test_base_rag_nodule.py @@ -0,0 +1,27 @@ +from griptape.engines.rag import RagContext +from tests.mocks.mock_rag_module import MockRagModule + + +class TestBaseRagModule: + def test_generate_query_prompt_stack(self): + prompt_stack = MockRagModule().generate_query_prompt_stack("test system", "test query") + + assert len(prompt_stack.messages) == 2 + assert prompt_stack.messages[0].is_system() + assert prompt_stack.messages[1].is_user() + + def test_get_context_param(self): + module = MockRagModule(name="boo") + context = RagContext(query="test") + + context.module_params["boo"] = {"foo": "bar"} + + assert module.get_context_param(context, "foo") == "bar" + + def test_set_context_param(self): + module = MockRagModule(name="boo") + context = RagContext(query="test") + + module.set_context_param(context, "foo", "bar") + + assert context.module_params["boo"]["foo"] == "bar" diff --git a/tests/unit/engines/rag/test_rag_engine.py b/tests/unit/engines/rag/test_rag_engine.py index b03ab9a1c..a39c0c2f1 100644 --- a/tests/unit/engines/rag/test_rag_engine.py +++ b/tests/unit/engines/rag/test_rag_engine.py @@ -1,8 +1,8 @@ import pytest from griptape.drivers import LocalVectorStoreDriver from griptape.engines.rag import RagEngine, RagContext -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_prompt_driver import MockPromptDriver @@ -13,18 +13,38 @@ def engine(self): return RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ - TextRetrievalRagModule( + VectorStoreRetrievalRagModule( vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) ) ] ), - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule(prompt_driver=MockPromptDriver()) - ), + response_stage=ResponseRagStage(response_module=PromptResponseRagModule(prompt_driver=MockPromptDriver())), + ) + + def test_module_name_uniqueness(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + + with pytest.raises(ValueError): + RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule(name="test", vector_store_driver=vector_store_driver), + VectorStoreRetrievalRagModule(name="test", vector_store_driver=vector_store_driver), + ] + ) + ) + + assert RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule(name="test1", vector_store_driver=vector_store_driver), + VectorStoreRetrievalRagModule(name="test2", vector_store_driver=vector_store_driver), + ] + ) ) def test_process_query(self, engine): assert engine.process_query("test").output.value == "mock output" def test_process(self, engine): - assert engine.process(RagContext(initial_query="test")).output.value == "mock output" + assert engine.process(RagContext(query="test")).output.value == "mock output" diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index 942a960f9..5dfcbc6d7 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -238,7 +238,7 @@ def test_task_memory_defaults(self): storage = list(agent.task_memory.artifact_storages.values())[0] assert isinstance(storage, TextArtifactStorage) - assert storage.rag_engine.generation_stage.generation_module.prompt_driver == prompt_driver + assert storage.rag_engine.response_stage.response_module.prompt_driver == prompt_driver assert ( storage.rag_engine.retrieval_stage.retrieval_modules[0].vector_store_driver.embedding_driver == embedding_driver diff --git a/tests/unit/tasks/test_rag_task.py b/tests/unit/tasks/test_rag_task.py index 75e5007ad..c9b82f208 100644 --- a/tests/unit/tasks/test_rag_task.py +++ b/tests/unit/tasks/test_rag_task.py @@ -1,7 +1,7 @@ import pytest from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import PromptGenerationRagModule -from griptape.engines.rag.stages import GenerationRagStage +from griptape.engines.rag.modules import PromptResponseRagModule +from griptape.engines.rag.stages import ResponseRagStage from griptape.structures import Agent from griptape.tasks import RagTask from tests.mocks.mock_prompt_driver import MockPromptDriver @@ -13,8 +13,8 @@ def task(self): return RagTask( input="test", rag_engine=RagEngine( - generation_stage=GenerationRagStage( - generation_module=PromptGenerationRagModule(prompt_driver=MockPromptDriver()) + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule(prompt_driver=MockPromptDriver()) ) ), ) diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index 082973bcb..210780729 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -166,10 +166,6 @@ def test_name(self): assert MockTool().name == "MockTool" assert MockTool(name="FooBar").name == "FooBar" - def test_class_name(self): - assert MockTool().class_name == "MockTool" - assert MockTool(name="FooBar").class_name == "MockTool" - def test_validate(self, tool): assert tool.validate() diff --git a/tests/utils/defaults.py b/tests/utils/defaults.py index f27410308..5a9f6f958 100644 --- a/tests/utils/defaults.py +++ b/tests/utils/defaults.py @@ -2,8 +2,8 @@ from griptape.drivers import LocalVectorStoreDriver from griptape.engines import PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import TextRetrievalRagModule, PromptGenerationRagModule -from griptape.engines.rag.stages import RetrievalRagStage, GenerationRagStage +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.memory import TaskMemory from griptape.memory.task.storage import TextArtifactStorage, BlobArtifactStorage from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -16,6 +16,7 @@ def text_tool_artifact_storage(): return TextArtifactStorage( rag_engine=rag_engine(MockPromptDriver(), vector_store_driver), vector_store_driver=vector_store_driver, + retrieval_rag_module_name="VectorStoreRetrievalRagModule", summary_engine=PromptSummaryEngine(prompt_driver=MockPromptDriver()), csv_extraction_engine=CsvExtractionEngine(prompt_driver=MockPromptDriver()), json_extraction_engine=JsonExtractionEngine(prompt_driver=MockPromptDriver()), @@ -31,7 +32,7 @@ def text_task_memory(name): def rag_engine(prompt_driver, vector_store_driver): return RagEngine( retrieval_stage=RetrievalRagStage( - retrieval_modules=[TextRetrievalRagModule(vector_store_driver=vector_store_driver)] + retrieval_modules=[VectorStoreRetrievalRagModule(vector_store_driver=vector_store_driver)] ), - generation_stage=GenerationRagStage(generation_module=PromptGenerationRagModule(prompt_driver=prompt_driver)), + response_stage=ResponseRagStage(response_module=PromptResponseRagModule(prompt_driver=prompt_driver)), ) From 83a16ac39159b9729f0108618ac85986c027d533 Mon Sep 17 00:00:00 2001 From: Matt Vallillo Date: Wed, 3 Jul 2024 13:47:05 -0500 Subject: [PATCH 37/87] Update `StructureVisualizer` (#936) --- griptape/utils/structure_visualizer.py | 10 +++++++--- tests/unit/utils/test_structure_visualizer.py | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/griptape/utils/structure_visualizer.py b/griptape/utils/structure_visualizer.py index 999519cf1..2a159a282 100644 --- a/griptape/utils/structure_visualizer.py +++ b/griptape/utils/structure_visualizer.py @@ -1,5 +1,6 @@ from __future__ import annotations import base64 +import hashlib from attrs import define, field from typing import TYPE_CHECKING @@ -36,7 +37,10 @@ def to_url(self) -> str: def __render_task(self, task: BaseTask) -> str: if task.children: - children = " & ".join([f"'{child.id}'" for child in task.children]) - return f"'{task.id}'--> {children};" + children = " & ".join([f"{self.__get_id(child.id)}({child.id})" for child in task.children]) + return f"{self.__get_id(task.id)}({task.id})--> {children};" else: - return f"'{task.id}';" + return f"{self.__get_id(task.id)}({task.id});" + + def __get_id(self, string: str) -> str: + return hashlib.md5(string.encode()).hexdigest()[:8] diff --git a/tests/unit/utils/test_structure_visualizer.py b/tests/unit/utils/test_structure_visualizer.py index 396b81166..e16275a5c 100644 --- a/tests/unit/utils/test_structure_visualizer.py +++ b/tests/unit/utils/test_structure_visualizer.py @@ -11,7 +11,7 @@ def test_agent(self): visualizer = StructureVisualizer(agent) result = visualizer.to_url() - assert result == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgkndGFzazEnOw==" + assert result == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgljYzVkYWYyNih0YXNrMSk7" def test_pipeline(self): pipeline = Pipeline( @@ -29,7 +29,7 @@ def test_pipeline(self): assert ( result - == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgkndGFzazEnLS0+ICd0YXNrMic7CgkndGFzazInLS0+ICd0YXNrMyc7CgkndGFzazMnLS0+ICd0YXNrNCc7CgkndGFzazQnOw==" + == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgljYzVkYWYyNih0YXNrMSktLT4gYWE1ZGU4N2UodGFzazIpOwoJYWE1ZGU4N2UodGFzazIpLS0+IDUxZmViYjIxKHRhc2szKTsKCTUxZmViYjIxKHRhc2szKS0tPiBhN2JlMzY4Yih0YXNrNCk7CglhN2JlMzY4Yih0YXNrNCk7" ) def test_workflow(self): @@ -48,5 +48,5 @@ def test_workflow(self): assert ( result - == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgkndGFzazEnLS0+ICd0YXNrMicgJiAndGFzazMnOwoJJ3Rhc2syJy0tPiAndGFzazQnOwoJJ3Rhc2szJy0tPiAndGFzazQnOwoJJ3Rhc2s0Jzs=" + == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgljYzVkYWYyNih0YXNrMSktLT4gYWE1ZGU4N2UodGFzazIpICYgNTFmZWJiMjEodGFzazMpOwoJYWE1ZGU4N2UodGFzazIpLS0+IGE3YmUzNjhiKHRhc2s0KTsKCTUxZmViYjIxKHRhc2szKS0tPiBhN2JlMzY4Yih0YXNrNCk7CglhN2JlMzY4Yih0YXNrNCk7" ) From d6cf531425ff205eae44259d9cc5008b2e4a237e Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 3 Jul 2024 15:37:15 -0500 Subject: [PATCH 38/87] Update pyright, fix new pyright errors (#934) --- poetry.lock | 19 +++++++++++++++---- pyproject.toml | 1 + 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/poetry.lock b/poetry.lock index f169895cc..83d2d5632 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohttp" @@ -4463,37 +4463,48 @@ files = [ {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab6b32544491ee655264dab86fc8a58e47c4f87d196b28022d4007faf971a50"}, {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:64bd6299e7fc888bb7f7292cf3e29504c406e5d5d04afd37ca994ab8142d8ee4"}, {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e914b650dd953b8d9b24ef56aa4ecbfc16e399227b68accd818f8bf159e0c558"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-none-win_amd64.whl", hash = "sha256:cb56a2149b0c4548a8e0158b071a943f33dae9b717f92b5c9ac34ccd1f5a958c"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f62620e023490902feca0109f306e122e427feff7d59e03ecd22c69a89452367"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:08d4c01d76da88cfe3d7d03b311b375ce3fb5a59130f93f0637bb755d6e56ff1"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524e276bc460176c79d7ba4b9131d9db73c534586660371ebdf067749252a33"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22863bc0aaf02ca2f5d76c8130929ae680b7d82dfc1c28c1ed5f306ff626928"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8cc82d57f6a91037e64a7aa9122f909576ef2a141a42ce599958ef9f8c4bc033"}, {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da8a053308210e44fd8349f07f45442a0691ac932f2881e98b05cf9ac404b091"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-none-win_amd64.whl", hash = "sha256:4baf3916c14364a815a64ead7f728afb61b37541933b2771f18dbb245029bb55"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:78db05deed0b32c9c75f2b3168a3a9b7d5e36487b218cb839bfe7e2a143450cb"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9af9446d605903c2b4e94621a9093f8d8a403729bc9cbfbcb62929f8238c838f"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c55890181d8d81e66cac25a95e215dc9680645d01e9091b64449d5407ad9bc6"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69344e7ae9964502a8693da7ad77ebc3e1418ee197e2e394bc23c5d4970772a"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b5db5c957a10d8cc2815085ba0b8fe09245b2f94c2225d9653a854a03b4217e1"}, {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03c19c21f63f9c91c590c4bbcc32cc2d8066b508c683a1d163b8c7d9816a01d5"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-none-win_amd64.whl", hash = "sha256:0230610779129f74ff802c744643ce7589b1d07cba21d046fe3b574281c29581"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b8cb9471ab4b2fa7e80d3ac4e580249ff988d782f2938ad1f0428433652b170d"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8081a5ace2658be91519902bde9ddc5f94e1f850a39be196007a25e3da5bbfdc"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69eababfa3200459276acd780a0f3eaf41d1fe7c02bd169e714cba422055b5b9"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632957fa671ebb841166e40913015de457225cb73600ef250c436c280e68bf45"}, {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2ce7ddef334b4e5c68f5ea1da1d65f686b8d84f4443059d128e0f069d3fa499a"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6ce333d450b158d582e36317089a006440b4e66739a8e8849d170e4cb15e8c8d"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-none-win_amd64.whl", hash = "sha256:9d9c85ce19db92362854f534807e470f03e905f283a7de6826dc79b790a8788e"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2503277f2a95a30e28e498570e2ed03ef4302f873054e8e21d6c0e607cbbc1d1"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8260395ef4ddae325e8b30cef0391adde7bd35e1a1decf8c729e26391f09b52d"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d8066b46d82bbaff5402d767e2f13d3449b8191c37bf8283e91d301a7159869"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9c42f6343cfbd6663fb53edc9eb9feb4ebf6186b284e22368adc1eeb6a33854"}, {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff534f491a059e74fb7f994876df86078b4b125dbecc53c098a298ecd55fa9c6"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b8fbf73b3ac513ddadafd338d61f79cd2370f0691d9175b2b92a45920920d6b"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-none-win_amd64.whl", hash = "sha256:a26447c82665d0e361207c1a15e56b0ca54974aa6c1fdfa18c68f908dec78cbe"}, {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24a16b8d55309f0af0db9d04ff442b0c91afccf078a94809e7c3a71747a5c214"}, {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c8fada56465fc19179404cc9d5d5e1064f5dfe27405cb052f57a5b4fe06aed1"}, {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a3d48d5abc146fd804395713427d944757a99254350e6a651e7d776818074aee"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:475829fe9994c66258157a8d4adb1c038f44f79f901208ba656d547842337227"}, {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef1ec0e97623bc0e18469418cc4dd2c59a2d5fddcae944de61e13c0b46f910e"}, {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91857b196de89e9b36d3f8629aa8772c0bbe7efef8334fe266956b1c192ec31c"}, {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:63831e407487b8a21bb51f97cd86a616c291d5138f8caec16ab6019cf6423935"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c30e61de93bcd0a9d3ca226b1ae5475002afde61e9d85018a6a4a040eeb86567"}, {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c72c37b03bce9900f5dbb4f476af17253ec60c13bf7a7259f71a8dc1b036cb"}, {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f1096165741b5c2178ab15b0eb09b5de16dd39b1cc135767d72471f0a69ce"}, {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:70c940c0e4ef335e22a6c705b01f286ee44780b5909065d212d94d82ea2580cb"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81c06f21757602d85f16dbc1cbaee1121cd65455f65aed4c048b7dcda7be85c4"}, + {file = "pyreqwest_impersonate-0.4.8.tar.gz", hash = "sha256:1eba11d47bd17244c64fec1502cc26ee66cc5c8a3be131e408101ae2b455e5bc"}, ] [package.extras] @@ -4501,13 +4512,13 @@ dev = ["pytest (>=8.1.1)"] [[package]] name = "pyright" -version = "1.1.363" +version = "1.1.370" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.363-py3-none-any.whl", hash = "sha256:d3b8d73c8d230e26cc3523862f3398032a0c39a00d7bb69dc0f595f8e888fd01"}, - {file = "pyright-1.1.363.tar.gz", hash = "sha256:00a8f0ae0e339473bb0488f8a2a2dcdf574e94a16cd7b4390d49d144714d8db2"}, + {file = "pyright-1.1.370-py3-none-any.whl", hash = "sha256:fc721601e480a69989775bfc210534a6ca0110ebd0c065244a8d3a151294fc61"}, + {file = "pyright-1.1.370.tar.gz", hash = "sha256:d0d559d506fc41e3297f721aaa05a1b9f06beda5acc9ac64ca371ce94c28f960"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index e4c84f624..dc7cb7877 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -215,6 +215,7 @@ exclude = [ pythonVersion = "3.9" reportOptionalMemberAccess = "none" reportIncompatibleVariableOverride = "none" # see thread: https://github.com/microsoft/pyright/issues/5933 +enableExperimentalFeatures = true # https://github.com/microsoft/pyright/issues/7713 [tool.pytest_env] OPENAI_API_KEY = {value = "api-key", skip_if_set = true} From c16f3f4ab9ea1e63bbb9229429970c5ca1f1162b Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 3 Jul 2024 16:06:58 -0500 Subject: [PATCH 39/87] Fix changelog (#938) --- CHANGELOG.md | 50 ++++++++++++++++++++++---------------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91c8fe89f..b96e0a724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,33 +5,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased -### Added -- `Message` for storing messages in a `PromptStack`. Messages consist of a role, content, and usage. -- `DeltaMessage` for storing partial messages in a `PromptStack`. Multiple `DeltaMessage` can be combined to form a `Message`. -- `TextMessageContent` for storing textual content in a `Message`. -- `ImageMessageContent` for storing image content in a `Message`. -- Support for adding `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s to `PromptStack`. -- Support for image inputs to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AmazonBedrockPromptDriver`, `AnthropicPromptDriver`, and `GooglePromptDriver`. -- Input/output token usage metrics to all Prompt Drivers. -- `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. -- Support for storing Artifacts as inputs/outputs in Conversation Memory Runs. -- `Agent.input` for passing Artifacts as input. -- Support for `PromptTask`s to take `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s as input. - -### Changed -- **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. -- **BREAKING**: Renamed `PromptStack.inputs` to `PromptStack.messages`. -- **BREAKING**: Moved `PromptStack.USER_ROLE`, `PromptStack.ASSISTANT_ROLE`, and `PromptStack.SYSTEM_ROLE` to `Message`. -- **BREAKING**: Updated return type of `PromptDriver.try_run` from `TextArtifact` to `Message`. -- **BREAKING**: Updated return type of `PromptDriver.try_stream` from `Iterator[TextArtifact]` to `Iterator[DeltaMessage]`. -- **BREAKING**: Removed `BasePromptEvent.token_count` in favor of `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. -- **BREAKING**: Removed `StartPromptEvent.prompt`. Use `StartPromptEvent.prompt_stack` instead. -- **BREAKING**: Removed `Agent.input_template` in favor of `Agent.input`. -- **BREAKING**: `BasePromptDriver.run` now returns a `Message` instead of a `TextArtifact`. For compatibility, `Message.value` contains the Message's Artifact value -- Default Prompt Driver model in `GoogleStructureConfig` to `gemini-1.5-pro`. - - - ### Added - `RagEngine` is an abstraction for implementing modular RAG pipelines. - `RagContext` is a container object for passing around RAG context. @@ -67,8 +40,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Parameter `fail_fast` to `Structure`. - `BooleanArtifact` for handling boolean values. - `typos` to dev dependencies to catch typos in code/docs. +- `Message` for storing messages in a `PromptStack`. Messages consist of a role, content, and usage. +- `DeltaMessage` for storing partial messages in a `PromptStack`. Multiple `DeltaMessage` can be combined to form a `Message`. +- `TextMessageContent` for storing textual content in a `Message`. +- `ImageMessageContent` for storing image content in a `Message`. +- Support for adding `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s to `PromptStack`. +- Support for image inputs to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AmazonBedrockPromptDriver`, `AnthropicPromptDriver`, and `GooglePromptDriver`. +- Input/output token usage metrics to all Prompt Drivers. +- `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. +- Support for storing Artifacts as inputs/outputs in Conversation Memory Runs. +- `Agent.input` for passing Artifacts as input. +- Support for `PromptTask`s to take `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s as input. ### Changed +- **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. +- **BREAKING**: Renamed `PromptStack.inputs` to `PromptStack.messages`. +- **BREAKING**: Moved `PromptStack.USER_ROLE`, `PromptStack.ASSISTANT_ROLE`, and `PromptStack.SYSTEM_ROLE` to `Message`. +- **BREAKING**: Updated return type of `PromptDriver.try_run` from `TextArtifact` to `Message`. +- **BREAKING**: Updated return type of `PromptDriver.try_stream` from `Iterator[TextArtifact]` to `Iterator[DeltaMessage]`. +- **BREAKING**: Removed `BasePromptEvent.token_count` in favor of `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. +- **BREAKING**: Removed `StartPromptEvent.prompt`. Use `StartPromptEvent.prompt_stack` instead. +- **BREAKING**: Removed `Agent.input_template` in favor of `Agent.input`. +- **BREAKING**: `BasePromptDriver.run` now returns a `Message` instead of a `TextArtifact`. For compatibility, `Message.value` contains the Message's Artifact value - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. - **BREAKING**: Removed `VectorQueryEngine` in favor of `RagEngine`. - **BREAKING**: Removed `TextQueryTask` in favor of `RagTask`. @@ -78,8 +71,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: Replaced `query_engine` with `vector_store_driver` in `VectorStoreClient`. - **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. - **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. -- `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. - **BREAKING**: All `futures_executor` fields renamed to `futures_executor_fn` and now accept callables instead of futures; wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. +- `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. +- Default Prompt Driver model in `GoogleStructureConfig` to `gemini-1.5-pro`. ### Fixed - `CoherePromptDriver` to properly handle empty history. From c785aba5d11f4dc375f1bcb638affc0337d5f523 Mon Sep 17 00:00:00 2001 From: datashaman Date: Fri, 5 Jul 2024 18:40:18 +0200 Subject: [PATCH 40/87] DynamoDB sort key (#917) --- CHANGELOG.md | 1 + .../drivers/conversation-memory-drivers.md | 1 + ...zon_dynamodb_conversation_memory_driver.py | 14 ++++- ...est_dynamodb_conversation_memory_driver.py | 53 +++++++++++++++++++ 4 files changed, 67 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b96e0a724..c02f822ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Support for storing Artifacts as inputs/outputs in Conversation Memory Runs. - `Agent.input` for passing Artifacts as input. - Support for `PromptTask`s to take `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s as input. +- Parameters `sort_key` and `sort_key_value` on `AmazonDynamoDbConversationMemoryDriver` for tables with sort keys. ### Changed - **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. diff --git a/docs/griptape-framework/drivers/conversation-memory-drivers.md b/docs/griptape-framework/drivers/conversation-memory-drivers.md index 4e437a3f5..88063292f 100644 --- a/docs/griptape-framework/drivers/conversation-memory-drivers.md +++ b/docs/griptape-framework/drivers/conversation-memory-drivers.md @@ -47,6 +47,7 @@ agent = Agent(conversation_memory=ConversationMemory(driver=dynamodb_driver)) agent.run("My name is Jeff.") agent.run("What is my name?") ``` +Optional parameters `sort_key` and `sort_key_value` can be supplied for tables with a composite primary key. ### Redis diff --git a/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py b/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py index 87c3667fe..36f62c0e5 100644 --- a/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py @@ -16,6 +16,8 @@ class AmazonDynamoDbConversationMemoryDriver(BaseConversationMemoryDriver): partition_key: str = field(kw_only=True, metadata={"serializable": True}) value_attribute_key: str = field(kw_only=True, metadata={"serializable": True}) partition_key_value: str = field(kw_only=True, metadata={"serializable": True}) + sort_key: Optional[str] = field(default=None, metadata={"serializable": True}) + sort_key_value: Optional[str | int] = field(default=None, metadata={"serializable": True}) table: Any = field(init=False) @@ -26,14 +28,14 @@ def __attrs_post_init__(self) -> None: def store(self, memory: BaseConversationMemory) -> None: self.table.update_item( - Key={self.partition_key: self.partition_key_value}, + Key=self._get_key(), UpdateExpression="set #attr = :value", ExpressionAttributeNames={"#attr": self.value_attribute_key}, ExpressionAttributeValues={":value": memory.to_json()}, ) def load(self) -> Optional[BaseConversationMemory]: - response = self.table.get_item(Key={self.partition_key: self.partition_key_value}) + response = self.table.get_item(Key=self._get_key()) if "Item" in response and self.value_attribute_key in response["Item"]: memory_value = response["Item"][self.value_attribute_key] @@ -45,3 +47,11 @@ def load(self) -> Optional[BaseConversationMemory]: return memory else: return None + + def _get_key(self) -> dict[str, str | int]: + key: dict[str, str | int] = {self.partition_key: self.partition_key_value} + + if self.sort_key is not None and self.sort_key_value is not None: + key[self.sort_key] = self.sort_key_value + + return key diff --git a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py index 80d77d24d..df0ca4d3c 100644 --- a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py @@ -60,6 +60,33 @@ def test_store(self): response = table.get_item(TableName=self.DYNAMODB_TABLE_NAME, Key={"entryId": "bar"}) assert "Item" in response + def test_store_with_sort_key(self): + session = boto3.Session(region_name=self.AWS_REGION) + dynamodb = session.resource("dynamodb") + table = dynamodb.Table(self.DYNAMODB_TABLE_NAME) + prompt_driver = MockPromptDriver() + memory_driver = AmazonDynamoDbConversationMemoryDriver( + session=session, + table_name=self.DYNAMODB_TABLE_NAME, + partition_key=self.DYNAMODB_PARTITION_KEY, + value_attribute_key=self.VALUE_ATTRIBUTE_KEY, + partition_key_value=self.PARTITION_KEY_VALUE, + sort_key="sortKey", + sort_key_value="foo" + ) + memory = ConversationMemory(driver=memory_driver) + pipeline = Pipeline(prompt_driver=prompt_driver, conversation_memory=memory) + + pipeline.add_task(PromptTask("test")) + + response = table.get_item(TableName=self.DYNAMODB_TABLE_NAME, Key={"entryId": "bar", "sortKey": "foo"}) + assert "Item" not in response + + pipeline.run() + + response = table.get_item(TableName=self.DYNAMODB_TABLE_NAME, Key={"entryId": "bar", "sortKey": "foo"}) + assert "Item" in response + def test_load(self): prompt_driver = MockPromptDriver() memory_driver = AmazonDynamoDbConversationMemoryDriver( @@ -83,3 +110,29 @@ def test_load(self): assert len(new_memory.runs) == 2 assert new_memory.runs[0].input.value == "test" assert new_memory.runs[0].output.value == "mock output" + + def test_load_with_sort_key(self): + prompt_driver = MockPromptDriver() + memory_driver = AmazonDynamoDbConversationMemoryDriver( + session=boto3.Session(region_name=self.AWS_REGION), + table_name=self.DYNAMODB_TABLE_NAME, + partition_key=self.DYNAMODB_PARTITION_KEY, + value_attribute_key=self.VALUE_ATTRIBUTE_KEY, + partition_key_value=self.PARTITION_KEY_VALUE, + sort_key="sortKey", + sort_key_value="foo" + ) + memory = ConversationMemory(driver=memory_driver) + pipeline = Pipeline(prompt_driver=prompt_driver, conversation_memory=memory) + + pipeline.add_task(PromptTask("test")) + + pipeline.run() + pipeline.run() + + new_memory = memory_driver.load() + + assert new_memory.type == "ConversationMemory" + assert len(new_memory.runs) == 2 + assert new_memory.runs[0].input.value == "test" + assert new_memory.runs[0].output.value == "mock output" \ No newline at end of file From 3e5bd038c351ca369d41c87740fa300b212564ce Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Fri, 5 Jul 2024 14:27:14 -0500 Subject: [PATCH 41/87] Update ruff linter rules according to documentation (#940) --- griptape/artifacts/base_artifact.py | 5 +- griptape/chunkers/base_chunker.py | 5 +- .../amazon_s3_file_manager_driver.py | 2 +- .../file_manager/base_file_manager_driver.py | 7 +- .../amazon_bedrock_image_generation_driver.py | 2 +- .../amazon_bedrock_image_query_driver.py | 2 +- .../drivers/prompt/anthropic_prompt_driver.py | 5 +- griptape/drivers/prompt/base_prompt_driver.py | 5 +- .../drivers/prompt/cohere_prompt_driver.py | 5 +- .../vector/base_vector_store_driver.py | 5 +- .../mongodb_atlas_vector_store_driver.py | 5 +- .../markdownify_web_scraper_driver.py | 67 +++++++++---------- .../duck_duck_go_web_search_driver.py | 2 +- griptape/loaders/base_text_loader.py | 5 +- griptape/loaders/sql_loader.py | 5 +- griptape/mixins/rule_mixin.py | 5 +- griptape/mixins/serializable_mixin.py | 2 +- griptape/schemas/polymorphic_schema.py | 8 +-- griptape/structures/structure.py | 12 +--- griptape/structures/workflow.py | 4 +- griptape/tasks/actions_subtask.py | 14 ++-- griptape/tasks/base_task.py | 2 +- griptape/tasks/prompt_task.py | 2 +- griptape/tokenizers/base_tokenizer.py | 3 +- griptape/utils/chat.py | 9 ++- griptape/utils/dict_utils.py | 2 +- griptape/utils/import_utils.py | 4 +- griptape/utils/load_artifact_from_memory.py | 4 +- pyproject.toml | 17 ++++- tests/utils/code_blocks.py | 3 +- 30 files changed, 98 insertions(+), 120 deletions(-) diff --git a/griptape/artifacts/base_artifact.py b/griptape/artifacts/base_artifact.py index a7a1811ea..ced8e0e1c 100644 --- a/griptape/artifacts/base_artifact.py +++ b/griptape/artifacts/base_artifact.py @@ -24,10 +24,7 @@ def value_to_bytes(cls, value: Any) -> bytes: @classmethod def value_to_dict(cls, value: Any) -> dict: - if isinstance(value, dict): - dict_value = value - else: - dict_value = json.loads(value) + dict_value = value if isinstance(value, dict) else json.loads(value) return {k: v for k, v in dict_value.items()} diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index 793bf24ad..26199a16c 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -58,10 +58,7 @@ def _chunk_recursively(self, chunk: str, current_separator: Optional[ChunkSepara # Iterate through the subchunks and calculate token counts. for index, subchunk in enumerate(subchunks): if index < len(subchunks): - if separator.is_prefix: - subchunk = separator.value + subchunk - else: - subchunk = subchunk + separator.value + subchunk = separator.value + subchunk if separator.is_prefix else subchunk + separator.value tokens_count += self.tokenizer.count_tokens(subchunk) diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index bdb4d787c..e2d794f31 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -55,7 +55,7 @@ def try_load_file(self, path: str) -> bytes: return response["Body"].read() except botocore.exceptions.ClientError as e: if e.response["Error"]["Code"] in {"NoSuchKey", "404"}: - raise FileNotFoundError + raise FileNotFoundError from e else: raise e diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index 562d8be4c..9b8fe8325 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -82,11 +82,8 @@ def save_file(self, path: str, value: bytes | str) -> InfoArtifact | ErrorArtifa encoding = None if loader is None else loader.encoding if isinstance(value, str): - if encoding is None: - value = value.encode() - else: - value = value.encode(encoding=encoding) - elif isinstance(value, bytearray) or isinstance(value, memoryview): + value = value.encode() if encoding is None else value.encode(encoding=encoding) + elif isinstance(value, (bytearray, memoryview)): raise ValueError(f"Unsupported type: {type(value)}") self.try_save_file(path, value) diff --git a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py index 2edb9f862..b5a4b7e3b 100644 --- a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py +++ b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py @@ -122,6 +122,6 @@ def _make_request(self, request: dict) -> bytes: try: image_bytes = self.image_generation_model_driver.get_generated_image(response_body) except Exception as e: - raise ValueError(f"Inpainting generation failed: {e}") + raise ValueError(f"Inpainting generation failed: {e}") from e return image_bytes diff --git a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py index eabe9d27e..e91cbbedc 100644 --- a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py +++ b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py @@ -32,4 +32,4 @@ def try_query(self, query: str, images: list[ImageArtifact]) -> TextArtifact: try: return self.image_query_model_driver.process_output(response_body) except Exception as e: - raise ValueError(f"Output is unable to be processed as returned {e}") + raise ValueError(f"Output is unable to be processed as returned {e}") from e diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 1dd7bb7f9..2c338c84c 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -77,10 +77,7 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: ) system_messages = prompt_stack.system_messages - if system_messages: - system_message = system_messages[0].to_text() - else: - system_message = None + system_message = system_messages[0].to_text() if system_messages else None return { "model": self.model, diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index f42e57081..b499179ed 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -65,10 +65,7 @@ def run(self, prompt_stack: PromptStack) -> Message: with attempt: self.before_run(prompt_stack) - if self.stream: - result = self.__process_stream(prompt_stack) - else: - result = self.__process_run(prompt_stack) + result = self.__process_stream(prompt_stack) if self.stream else self.__process_run(prompt_stack) self.after_run(result) diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index 331c2c039..b00abd855 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -79,10 +79,7 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: ) system_messages = prompt_stack.system_messages - if system_messages: - preamble = system_messages[0].to_text() - else: - preamble = None + preamble = system_messages[0].to_text() if system_messages else None return { "message": user_message, diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 5a4130a88..72ed2c322 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -64,10 +64,7 @@ def upsert_text_artifact( else: meta["artifact"] = artifact.to_json() - if artifact.embedding: - vector = artifact.embedding - else: - vector = artifact.generate_embedding(self.embedding_driver) + vector = artifact.embedding if artifact.embedding else artifact.generate_embedding(self.embedding_driver) if isinstance(vector, list): return self.upsert_vector(vector, vector_id=vector_id, namespace=namespace, meta=meta, **kwargs) diff --git a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py index 73bcc02c7..e60524714 100644 --- a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py +++ b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py @@ -90,10 +90,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD Entries can optionally be filtered by namespace. """ collection = self.get_collection() - if namespace is None: - cursor = collection.find() - else: - cursor = collection.find({"namespace": namespace}) + cursor = collection.find() if namespace is None else collection.find({"namespace": namespace}) return [ BaseVectorStoreDriver.Entry( diff --git a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py index eb33aeb19..28f225ba8 100644 --- a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py @@ -48,51 +48,50 @@ def convert_a(self, el, text, convert_as_inline): return super().convert_a(el, text, convert_as_inline) return text - with sync_playwright() as p: - with p.chromium.launch(headless=True) as browser: - page = browser.new_page() + with sync_playwright() as p, p.chromium.launch(headless=True) as browser: + page = browser.new_page() - def skip_loading_images(route): - if route.request.resource_type == "image": - return route.abort() - route.continue_() + def skip_loading_images(route): + if route.request.resource_type == "image": + return route.abort() + route.continue_() - page.route("**/*", skip_loading_images) + page.route("**/*", skip_loading_images) - page.goto(url) + page.goto(url) - # Some websites require a delay before the content is fully loaded - # even after the browser has emitted "load" event. - if self.timeout: - page.wait_for_timeout(self.timeout) + # Some websites require a delay before the content is fully loaded + # even after the browser has emitted "load" event. + if self.timeout: + page.wait_for_timeout(self.timeout) - content = page.content() + content = page.content() - if not content: - raise Exception("can't access URL") + if not content: + raise Exception("can't access URL") - soup = BeautifulSoup(content, "html.parser") + soup = BeautifulSoup(content, "html.parser") - # Remove unwanted elements - exclude_selector = ",".join( - self.exclude_tags + [f".{c}" for c in self.exclude_classes] + [f"#{i}" for i in self.exclude_ids] - ) - if exclude_selector: - for s in soup.select(exclude_selector): - s.extract() + # Remove unwanted elements + exclude_selector = ",".join( + self.exclude_tags + [f".{c}" for c in self.exclude_classes] + [f"#{i}" for i in self.exclude_ids] + ) + if exclude_selector: + for s in soup.select(exclude_selector): + s.extract() - text = OptionalLinksMarkdownConverter().convert_soup(soup) + text = OptionalLinksMarkdownConverter().convert_soup(soup) - # Remove leading and trailing whitespace from the entire text - text = text.strip() + # Remove leading and trailing whitespace from the entire text + text = text.strip() - # Remove trailing whitespace from each line - text = re.sub(r"[ \t]+$", "", text, flags=re.MULTILINE) + # Remove trailing whitespace from each line + text = re.sub(r"[ \t]+$", "", text, flags=re.MULTILINE) - # Indent using 2 spaces instead of tabs - text = re.sub(r"(\n?\s*?)\t", r"\1 ", text) + # Indent using 2 spaces instead of tabs + text = re.sub(r"(\n?\s*?)\t", r"\1 ", text) - # Remove triple+ newlines (keep double newlines for paragraphs) - text = re.sub(r"\n\n+", "\n\n", text) + # Remove triple+ newlines (keep double newlines for paragraphs) + text = re.sub(r"\n\n+", "\n\n", text) - return TextArtifact(text) + return TextArtifact(text) diff --git a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py index 9b90bf5ff..ade6ed85c 100644 --- a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py +++ b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py @@ -26,4 +26,4 @@ def search(self, query: str, **kwargs) -> ListArtifact: ] ) except Exception as e: - raise Exception(f"Error searching '{query}' with DuckDuckGo: {e}") + raise Exception(f"Error searching '{query}' with DuckDuckGo: {e}") from e diff --git a/griptape/loaders/base_text_loader.py b/griptape/loaders/base_text_loader.py index f09b57902..c2840d62f 100644 --- a/griptape/loaders/base_text_loader.py +++ b/griptape/loaders/base_text_loader.py @@ -41,10 +41,7 @@ def load_collection(self, sources: list[Any], *args, **kwargs) -> dict[str, Erro def _text_to_artifacts(self, text: str) -> list[TextArtifact]: artifacts = [] - if self.chunker: - chunks = self.chunker.chunk(text) - else: - chunks = [TextArtifact(text)] + chunks = self.chunker.chunk(text) if self.chunker else [TextArtifact(text)] if self.embedding_driver: for chunk in chunks: diff --git a/griptape/loaders/sql_loader.py b/griptape/loaders/sql_loader.py index c20fb022d..e6979e324 100644 --- a/griptape/loaders/sql_loader.py +++ b/griptape/loaders/sql_loader.py @@ -16,10 +16,7 @@ def load(self, source: str, *args, **kwargs) -> list[CsvRowArtifact]: rows = self.sql_driver.execute_query(source) artifacts = [] - if rows: - chunks = [CsvRowArtifact(row.cells) for row in rows] - else: - chunks = [] + chunks = [CsvRowArtifact(row.cells) for row in rows] if rows else [] if self.embedding_driver: for chunk in chunks: diff --git a/griptape/mixins/rule_mixin.py b/griptape/mixins/rule_mixin.py index a89309a15..0cc696242 100644 --- a/griptape/mixins/rule_mixin.py +++ b/griptape/mixins/rule_mixin.py @@ -49,10 +49,7 @@ def all_rulesets(self) -> list[Ruleset]: if self.rulesets: task_rulesets = self.rulesets elif self.rules: - if structure_rulesets: - task_ruleset_name = self.ADDITIONAL_RULESET_NAME - else: - task_ruleset_name = self.DEFAULT_RULESET_NAME + task_ruleset_name = self.ADDITIONAL_RULESET_NAME if structure_rulesets else self.DEFAULT_RULESET_NAME task_rulesets = [Ruleset(name=task_ruleset_name, rules=self.rules)] diff --git a/griptape/mixins/serializable_mixin.py b/griptape/mixins/serializable_mixin.py index c7a0bf035..667ae752d 100644 --- a/griptape/mixins/serializable_mixin.py +++ b/griptape/mixins/serializable_mixin.py @@ -42,7 +42,7 @@ def get_schema(cls: type[T], subclass_name: Optional[str] = None) -> Schema: @classmethod def from_dict(cls: type[T], data: dict) -> T: - return cast(T, cls.get_schema(subclass_name=data["type"] if "type" in data else None).load(data)) + return cast(T, cls.get_schema(subclass_name=data.get("type")).load(data)) @classmethod def from_json(cls: type[T], data: str) -> T: diff --git a/griptape/schemas/polymorphic_schema.py b/griptape/schemas/polymorphic_schema.py index 534ba8ffc..452e3001f 100644 --- a/griptape/schemas/polymorphic_schema.py +++ b/griptape/schemas/polymorphic_schema.py @@ -58,12 +58,12 @@ def _dump(self, obj, *, update_fields=True, **kwargs): obj_type = self.get_obj_type(obj) if not obj_type: - return (None, {"_schema": "Unknown object class: %s" % obj.__class__.__name__}) + return (None, {"_schema": f"Unknown object class: {obj.__class__.__name__}"}) type_schema = BaseSchema.from_attrs_cls(obj.__class__) if not type_schema: - return None, {"_schema": "Unsupported object type: %s" % obj_type} + return None, {"_schema": f"Unsupported object type: {obj_type}"} schema = type_schema if isinstance(type_schema, Schema) else type_schema() @@ -110,7 +110,7 @@ def load(self, data, *, many=None, partial=None, unknown=None, **kwargs): def _load(self, data, *, partial=None, unknown=None, **kwargs): if not isinstance(data, dict): - raise ValidationError({"_schema": "Invalid data type: %s" % data}) + raise ValidationError({"_schema": f"Invalid data type: {data}"}) data = dict(data) unknown = unknown or self.unknown @@ -121,7 +121,7 @@ def _load(self, data, *, partial=None, unknown=None, **kwargs): type_schema = self.inner_class.get_schema(data_type) if not type_schema: - raise ValidationError({self.type_field: ["Unsupported value: %s" % data_type]}) + raise ValidationError({self.type_field: [f"Unsupported value: {data_type}"]}) schema = type_schema if isinstance(type_schema, Schema) else type_schema() diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 18e7d1284..c7b779590 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -147,15 +147,9 @@ def default_config(self) -> BaseStructureConfig: if self.prompt_driver is not None or self.embedding_driver is not None or self.stream is not None: config = StructureConfig() - if self.prompt_driver is None: - prompt_driver = OpenAiChatPromptDriver(model="gpt-4o") - else: - prompt_driver = self.prompt_driver - - if self.embedding_driver is None: - embedding_driver = OpenAiEmbeddingDriver() - else: - embedding_driver = self.embedding_driver + prompt_driver = OpenAiChatPromptDriver(model="gpt-4o") if self.prompt_driver is None else self.prompt_driver + + embedding_driver = OpenAiEmbeddingDriver() if self.embedding_driver is None else self.embedding_driver if self.stream is not None: prompt_driver.stream = self.stream diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 3689f7330..f7bc2e893 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -89,8 +89,8 @@ def insert_task( try: parent_index = self.tasks.index(parent_task) - except ValueError: - raise ValueError(f"Parent task {parent_task.id} not found in workflow.") + except ValueError as exc: + raise ValueError(f"Parent task {parent_task.id} not found in workflow.") from exc else: if parent_index > last_parent_index: last_parent_index = parent_index diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index fa2aff822..c835f2b84 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -112,11 +112,10 @@ def run(self) -> BaseArtifact: self.structure.logger.error(f"Subtask {self.id}\n{e}", exc_info=True) self.output = ErrorArtifact(str(e), exception=e) - finally: - if self.output is not None: - return self.output - else: - return ErrorArtifact("no tool output") + if self.output is not None: + return self.output + else: + return ErrorArtifact("no tool output") def execute_actions(self, actions: list[Action]) -> list[tuple[str, BaseArtifact]]: with self.futures_executor_fn() as executor: @@ -234,9 +233,8 @@ def __parse_actions(self, actions_matches: list[str]) -> None: tag=action_tag, name=action_name, path=action_path, input=action_input, tool=tool ) - if new_action.tool: - if new_action.input: - self.__validate_action(new_action) + if new_action.tool and new_action.input: + self.__validate_action(new_action) # Don't forget to add it to the subtask actions list! self.actions.append(new_action) diff --git a/griptape/tasks/base_task.py b/griptape/tasks/base_task.py index be5ff94d8..9aa891e18 100644 --- a/griptape/tasks/base_task.py +++ b/griptape/tasks/base_task.py @@ -144,7 +144,7 @@ def execute(self) -> Optional[BaseArtifact]: finally: self.state = BaseTask.State.FINISHED - return self.output + return self.output def can_execute(self) -> bool: return self.state == BaseTask.State.PENDING and all(parent.is_finished() for parent in self.parents) diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index dba542d60..955855e3d 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -102,7 +102,7 @@ def _process_task_input( return self._process_task_input(task_input(self)) elif isinstance(task_input, BaseArtifact): return task_input - elif isinstance(task_input, list) or isinstance(task_input, tuple): + elif isinstance(task_input, (list, tuple)): return ListArtifact([self._process_task_input(elem) for elem in task_input]) else: return self._process_task_input(TextArtifact(task_input)) diff --git a/griptape/tokenizers/base_tokenizer.py b/griptape/tokenizers/base_tokenizer.py index 474ccbaa5..212e40058 100644 --- a/griptape/tokenizers/base_tokenizer.py +++ b/griptape/tokenizers/base_tokenizer.py @@ -1,6 +1,6 @@ from __future__ import annotations import logging -from abc import ABC +from abc import ABC, abstractmethod from attrs import define, field, Factory @@ -40,6 +40,7 @@ def count_output_tokens_left(self, text: str) -> int: else: return 0 + @abstractmethod def count_tokens(self, text: str) -> int: ... def _default_max_input_tokens(self) -> int: diff --git a/griptape/utils/chat.py b/griptape/utils/chat.py index 12653ce9e..f78d311f9 100644 --- a/griptape/utils/chat.py +++ b/griptape/utils/chat.py @@ -1,6 +1,9 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Callable + +from typing import TYPE_CHECKING, Callable, Optional + from attrs import Factory, define, field + from griptape.utils.stream import Stream if TYPE_CHECKING: @@ -22,9 +25,9 @@ class Chat: def default_output_fn(self, text: str) -> None: if self.structure.config.prompt_driver.stream: - print(text, end="", flush=True) + print(text, end="", flush=True) # noqa T201 else: - print(text) + print(text) # noqa T201 def start(self) -> None: if self.intro_text: diff --git a/griptape/utils/dict_utils.py b/griptape/utils/dict_utils.py index 64a91d68b..c5f6bb676 100644 --- a/griptape/utils/dict_utils.py +++ b/griptape/utils/dict_utils.py @@ -30,7 +30,7 @@ def dict_merge(dct: dict, merge_dct: dict, add_keys: bool = True) -> dict: if not add_keys: merge_dct = {k: merge_dct[k] for k in set(dct).intersection(set(merge_dct))} - for key in merge_dct.keys(): + for key in merge_dct: if key in dct and isinstance(dct[key], dict): dct[key] = dict_merge(dct[key], merge_dct[key], add_keys=add_keys) else: diff --git a/griptape/utils/import_utils.py b/griptape/utils/import_utils.py index 5e00551f8..0de09b2d1 100644 --- a/griptape/utils/import_utils.py +++ b/griptape/utils/import_utils.py @@ -32,8 +32,8 @@ def import_optional_dependency(name: str) -> Optional[ModuleType]: ) try: module = import_module(name) - except ImportError: - raise ImportError(msg) + except ImportError as exc: + raise ImportError(msg) from exc return module diff --git a/griptape/utils/load_artifact_from_memory.py b/griptape/utils/load_artifact_from_memory.py index 6ab823130..af11b8ae8 100644 --- a/griptape/utils/load_artifact_from_memory.py +++ b/griptape/utils/load_artifact_from_memory.py @@ -14,8 +14,8 @@ def load_artifact_from_memory( try: artifact = [a for a in artifacts if a.name == artifact_name][0] - except IndexError: - raise ValueError(f"artifact {artifact_name} not found in namespace {artifact_namespace}") + except IndexError as exc: + raise ValueError(f"artifact {artifact_name} not found in namespace {artifact_namespace}") from exc if not isinstance(artifact, artifact_type): raise ValueError(f"{artifact.name} is not of type {artifact_type}") diff --git a/pyproject.toml b/pyproject.toml index dc7cb7877..c1b6b934c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -200,7 +200,22 @@ line-length = 120 skip-magic-trailing-comma = true [tool.ruff.lint] -select = ["E4", "E7", "E9", "F", "TID251"] +select = [ + "E", # pycodestyle + "F", # Pyflakes + "UP", # pyupgrade + "B", # flake8-bugbear + "SIM", # flake8-simplify + "TID251", # banned-api + "T201", # print +] +ignore = [ + "UP007", # non-pep604-annotation + "E501", # line-too-long + "B024", # abstract-base-class-without-abstract-method + "B009", # get-attr-with-constant + "B010", # set-attr-with-constant +] [tool.ruff.lint.flake8-tidy-imports.banned-api] "attr".msg = "The attr module is deprecated, use attrs instead." diff --git a/tests/utils/code_blocks.py b/tests/utils/code_blocks.py index 09a4695ba..9cfebb987 100644 --- a/tests/utils/code_blocks.py +++ b/tests/utils/code_blocks.py @@ -1,3 +1,4 @@ +import logging import pathlib import textwrap @@ -13,7 +14,7 @@ def check_py_string(source: str) -> None: try: exec(source, {"__MODULE__": "__main__"}) except Exception: - print(source) + logging.info(source) raise From 731c3bb46272d338fdd2bb8c9ec2b247d3f076f6 Mon Sep 17 00:00:00 2001 From: Vasily Vasinov Date: Mon, 8 Jul 2024 14:07:27 -0600 Subject: [PATCH 42/87] `FootnotePromptResponseRagModule`, `TextLoaderRetrievalRagModule`, and more (#942) --- CHANGELOG.md | 3 ++ .../griptape-framework/engines/rag-engines.md | 4 +- griptape/artifacts/base_artifact.py | 9 +++- griptape/artifacts/boolean_artifact.py | 3 +- griptape/artifacts/text_artifact.py | 3 +- griptape/common/__init__.py | 3 ++ .../contents/base_message_content.py | 9 ++-- griptape/common/reference.py | 14 +++++ .../drivers/rerank/cohere_rerank_driver.py | 5 +- .../vector/base_vector_store_driver.py | 26 +++++---- griptape/engines/rag/modules/__init__.py | 4 ++ .../engines/rag/modules/base_rag_module.py | 8 +-- .../footnote_prompt_response_rag_module.py | 18 +++++++ .../response/prompt_response_rag_module.py | 53 ++++++++----------- .../text_loader_retrieval_rag_module.py | 41 ++++++++++++++ .../vector_store_retrieval_rag_module.py | 4 +- griptape/engines/rag/rag_context.py | 30 +++++++---- griptape/loaders/base_text_loader.py | 18 ++++--- .../task/storage/text_artifact_storage.py | 2 +- griptape/schemas/base_schema.py | 7 ++- .../response/footnote_prompt/system.j2 | 37 +++++++++++++ .../rag/modules/response/prompt/system.j2 | 5 +- griptape/utils/__init__.py | 2 + griptape/utils/dict_utils.py | 9 +++- griptape/utils/reference_utils.py | 12 +++++ tests/mocks/mock_serializable.py | 5 ++ ...est_dynamodb_conversation_memory_driver.py | 6 +-- .../rerank/test_cohere_rerank_driver.py | 11 +++- ...est_in_memory_local_vector_store_driver.py | 10 ---- .../vector/test_local_vector_store_driver.py | 23 ++++++++ ...est_footnote_prompt_response_rag_module.py | 33 ++++++++++++ ...est_metadata_before_response_rag_module.py | 6 ++- .../test_prompt_response_rag_module.py | 6 +-- .../test_text_chunks_rerank_rag_module.py | 14 +++-- .../test_text_loader_retrieval_rag_module.py | 26 +++++++++ .../test_vector_store_retrieval_rag_module.py | 9 ++-- .../rag/modules/test_base_rag_nodule.py | 4 +- tests/unit/engines/rag/test_rag_context.py | 23 ++++++++ tests/unit/mixins/test_seriliazable_mixin.py | 17 ++++-- tests/unit/utils/test_dict_utils.py | 21 ++++++-- tests/utils/test_reference_utils.py | 22 ++++++++ 41 files changed, 450 insertions(+), 115 deletions(-) create mode 100644 griptape/common/reference.py create mode 100644 griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py create mode 100644 griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 create mode 100644 griptape/utils/reference_utils.py delete mode 100644 tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py create mode 100644 tests/unit/drivers/vector/test_local_vector_store_driver.py create mode 100644 tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py create mode 100644 tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py create mode 100644 tests/unit/engines/rag/test_rag_context.py create mode 100644 tests/utils/test_reference_utils.py diff --git a/CHANGELOG.md b/CHANGELOG.md index c02f822ec..65634a8e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,12 +15,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - RAG modules: - Retrieval: - `VectorStoreRetrievalRagModule` for retrieving text chunks from vector stores. + - `TextLoaderRetrievalRagModule` for retrieving data with text loaders in real time. - `TextChunksRerankRagModule` for re-ranking retrieved results. - Response: - `MetadataBeforeResponseRagModule` for appending metadata. - `RulesetsBeforeResponseRagModule` for appending rulesets. - `PromptResponseRagModule` for generating responses based on retrieved text chunks. - `TextChunksResponseRagModule` for responding with retrieved text chunks. + - `FootnotePromptResponseRagModule` for responding with automatic footnotes from text chunk references. - `RagClient` tool for exposing `RagEngines` to LLM agents. - `RagTask` task for including `RagEngines` in any structure. - Rerank drivers: @@ -52,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Agent.input` for passing Artifacts as input. - Support for `PromptTask`s to take `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s as input. - Parameters `sort_key` and `sort_key_value` on `AmazonDynamoDbConversationMemoryDriver` for tables with sort keys. +- `Reference` for supporting artifact citations in loaders and RAG engine modules. ### Changed - **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. diff --git a/docs/griptape-framework/engines/rag-engines.md b/docs/griptape-framework/engines/rag-engines.md index c03bf0f47..9d71aaa80 100644 --- a/docs/griptape-framework/engines/rag-engines.md +++ b/docs/griptape-framework/engines/rag-engines.md @@ -20,13 +20,15 @@ No modules implemented yet. #### Retrieval - `TextRetrievalRagModule` is for retrieving text chunks. +- `TextLoaderRetrievalRagModule` is for retrieving data with text loaders in real time. - `TextChunksRerankRagModule` is for re-ranking retrieved results. #### Response - `MetadataBeforeResponseRagModule` is for appending metadata. - `RulesetsBeforeResponseRagModule` is for appending rulesets. - `PromptResponseRagModule` is for generating responses based on retrieved text chunks. -- `TextChunksResponseRagModule` for responding with retrieved text chunks. +- `TextChunksResponseRagModule` is for responding with retrieved text chunks. +- `FootnotePromptResponseRagModule` is for responding with automatic footnotes from text chunk references. ### Example diff --git a/griptape/artifacts/base_artifact.py b/griptape/artifacts/base_artifact.py index ced8e0e1c..626e13f69 100644 --- a/griptape/artifacts/base_artifact.py +++ b/griptape/artifacts/base_artifact.py @@ -1,15 +1,20 @@ from __future__ import annotations from griptape.mixins import SerializableMixin -from typing import Any +from typing import Any, TYPE_CHECKING, Optional import json import uuid from abc import ABC, abstractmethod from attrs import define, field, Factory +if TYPE_CHECKING: + from griptape.common import Reference -@define() + +@define class BaseArtifact(SerializableMixin, ABC): id: str = field(default=Factory(lambda: uuid.uuid4().hex), kw_only=True, metadata={"serializable": True}) + reference: Optional[Reference] = field(default=None, kw_only=True, metadata={"serializable": True}) + meta: dict[str, Any] = field(factory=dict, kw_only=True, metadata={"serializable": True}) name: str = field( default=Factory(lambda self: self.id, takes_self=True), kw_only=True, metadata={"serializable": True} ) diff --git a/griptape/artifacts/boolean_artifact.py b/griptape/artifacts/boolean_artifact.py index a7a84da18..e7e440f45 100644 --- a/griptape/artifacts/boolean_artifact.py +++ b/griptape/artifacts/boolean_artifact.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import Any, Union +from typing import Union from attrs import define, field from griptape.artifacts import BaseArtifact @@ -7,7 +7,6 @@ @define class BooleanArtifact(BaseArtifact): value: bool = field(converter=bool, metadata={"serializable": True}) - meta: dict[str, Any] = field(factory=dict, kw_only=True, metadata={"serializable": True}) @classmethod def parse_bool(cls, value: Union[str, bool]) -> BooleanArtifact: diff --git a/griptape/artifacts/text_artifact.py b/griptape/artifacts/text_artifact.py index 8b83303f0..e8a2bb2a7 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Optional from attrs import define, field from griptape.artifacts import BaseArtifact @@ -13,7 +13,6 @@ class TextArtifact(BaseArtifact): value: str = field(converter=str, metadata={"serializable": True}) encoding: str = field(default="utf-8", kw_only=True) encoding_error_handler: str = field(default="strict", kw_only=True) - meta: dict[str, Any] = field(factory=dict, kw_only=True, metadata={"serializable": True}) _embedding: list[float] = field(factory=list, kw_only=True) @property diff --git a/griptape/common/__init__.py b/griptape/common/__init__.py index 2b1189472..6e357323a 100644 --- a/griptape/common/__init__.py +++ b/griptape/common/__init__.py @@ -10,6 +10,8 @@ from .prompt_stack.prompt_stack import PromptStack +from .reference import Reference + __all__ = [ "BaseMessage", "BaseDeltaMessageContent", @@ -20,4 +22,5 @@ "TextMessageContent", "ImageMessageContent", "PromptStack", + "Reference", ] diff --git a/griptape/common/prompt_stack/contents/base_message_content.py b/griptape/common/prompt_stack/contents/base_message_content.py index cd4d5bd92..28a9e317e 100644 --- a/griptape/common/prompt_stack/contents/base_message_content.py +++ b/griptape/common/prompt_stack/contents/base_message_content.py @@ -1,15 +1,14 @@ from __future__ import annotations - from abc import ABC from collections.abc import Sequence - +from typing import TYPE_CHECKING from attrs import define, field - -from griptape.artifacts.base_artifact import BaseArtifact from griptape.mixins import SerializableMixin - from .base_delta_message_content import BaseDeltaMessageContent +if TYPE_CHECKING: + from griptape.artifacts.base_artifact import BaseArtifact + @define class BaseMessageContent(ABC, SerializableMixin): diff --git a/griptape/common/reference.py b/griptape/common/reference.py new file mode 100644 index 000000000..d92c203f9 --- /dev/null +++ b/griptape/common/reference.py @@ -0,0 +1,14 @@ +import uuid +from typing import Optional +from attrs import define, field, Factory +from griptape.mixins import SerializableMixin + + +@define(kw_only=True) +class Reference(SerializableMixin): + id: str = field(default=Factory(lambda: uuid.uuid4().hex), metadata={"serializable": True}) + title: str = field(metadata={"serializable": True}) + authors: list[str] = field(factory=list, metadata={"serializable": True}) + source: Optional[str] = field(default=None, metadata={"serializable": True}) + year: Optional[str] = field(default=None, metadata={"serializable": True}) + url: Optional[str] = field(default=None, metadata={"serializable": True}) diff --git a/griptape/drivers/rerank/cohere_rerank_driver.py b/griptape/drivers/rerank/cohere_rerank_driver.py index 206706476..57a7863d4 100644 --- a/griptape/drivers/rerank/cohere_rerank_driver.py +++ b/griptape/drivers/rerank/cohere_rerank_driver.py @@ -20,12 +20,13 @@ class CohereRerankDriver(BaseRerankDriver): ) def run(self, query: str, artifacts: list[TextArtifact]) -> list[TextArtifact]: + artifacts_dict = {str(hash(a.value)): a for a in artifacts} response = self.client.rerank( model=self.model, query=query, - documents=[a.value for a in artifacts], + documents=[a.value for a in artifacts_dict.values()], return_documents=True, top_n=self.top_n, ) - return [TextArtifact(r.document.text) for r in response.results] + return [artifacts_dict[str(hash(r.document.text))] for r in response.results] diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 72ed2c322..2957d7557 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -37,16 +37,21 @@ def to_artifact(self) -> BaseArtifact: ) def upsert_text_artifacts( - self, artifacts: dict[str, list[TextArtifact]], meta: Optional[dict] = None, **kwargs + self, artifacts: list[TextArtifact] | dict[str, list[TextArtifact]], meta: Optional[dict] = None, **kwargs ) -> None: with self.futures_executor_fn() as executor: - utils.execute_futures_dict( - { - namespace: executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) - for namespace, artifact_list in artifacts.items() - for a in artifact_list - } - ) + if isinstance(artifacts, list): + utils.execute_futures_list( + [executor.submit(self.upsert_text_artifact, a, None, meta, **kwargs) for a in artifacts] + ) + else: + utils.execute_futures_dict( + { + namespace: executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) + for namespace, artifact_list in artifacts.items() + for a in artifact_list + } + ) def upsert_text_artifact( self, @@ -57,7 +62,10 @@ def upsert_text_artifact( **kwargs, ) -> str: meta = {} if meta is None else meta - vector_id = self._get_default_vector_id(artifact.to_text()) if vector_id is None else vector_id + + if vector_id is None: + value = artifact.to_text() if artifact.reference is None else artifact.to_text() + str(artifact.reference) + vector_id = self._get_default_vector_id(value) if self.does_entry_exist(vector_id, namespace): return vector_id diff --git a/griptape/engines/rag/modules/__init__.py b/griptape/engines/rag/modules/__init__.py index cb11551e3..4a180490d 100644 --- a/griptape/engines/rag/modules/__init__.py +++ b/griptape/engines/rag/modules/__init__.py @@ -4,6 +4,7 @@ from .retrieval.base_rerank_rag_module import BaseRerankRagModule from .retrieval.text_chunks_rerank_rag_module import TextChunksRerankRagModule from .retrieval.vector_store_retrieval_rag_module import VectorStoreRetrievalRagModule +from .retrieval.text_loader_retrieval_rag_module import TextLoaderRetrievalRagModule from .response.base_before_response_rag_module import BaseBeforeResponseRagModule from .response.base_after_response_rag_module import BaseAfterResponseRagModule from .response.base_response_rag_module import BaseResponseRagModule @@ -11,6 +12,7 @@ from .response.rulesets_before_response_rag_module import RulesetsBeforeResponseRagModule from .response.metadata_before_response_rag_module import MetadataBeforeResponseRagModule from .response.text_chunks_response_rag_module import TextChunksResponseRagModule +from .response.footnote_prompt_response_rag_module import FootnotePromptResponseRagModule __all__ = [ "BaseRagModule", @@ -19,6 +21,7 @@ "BaseRerankRagModule", "TextChunksRerankRagModule", "VectorStoreRetrievalRagModule", + "TextLoaderRetrievalRagModule", "BaseBeforeResponseRagModule", "BaseAfterResponseRagModule", "BaseResponseRagModule", @@ -26,4 +29,5 @@ "RulesetsBeforeResponseRagModule", "MetadataBeforeResponseRagModule", "TextChunksResponseRagModule", + "FootnotePromptResponseRagModule", ] diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py index becd94d9e..9bdcb6372 100644 --- a/griptape/engines/rag/modules/base_rag_module.py +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -19,10 +19,10 @@ def generate_query_prompt_stack(self, system_prompt: str, query: str) -> PromptS ) def get_context_param(self, context: RagContext, key: str) -> Optional[Any]: - return context.module_params.get(self.name, {}).get(key) + return context.module_configs.get(self.name, {}).get(key) def set_context_param(self, context: RagContext, key: str, value: Any) -> None: - if not isinstance(context.module_params.get(self.name), dict): - context.module_params[self.name] = {} + if not isinstance(context.module_configs.get(self.name), dict): + context.module_configs[self.name] = {} - context.module_params[self.name][key] = value + context.module_configs[self.name][key] = value diff --git a/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py b/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py new file mode 100644 index 000000000..c64c8e5ee --- /dev/null +++ b/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py @@ -0,0 +1,18 @@ +from attrs import define + +from griptape import utils +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import PromptResponseRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class FootnotePromptResponseRagModule(PromptResponseRagModule): + def default_system_template_generator(self, context: RagContext, artifacts: list[TextArtifact]) -> str: + return J2("engines/rag/modules/response/footnote_prompt/system.j2").render( + text_chunk_artifacts=artifacts, + references=utils.references_from_artifacts(artifacts), + before_system_prompt="\n\n".join(context.before_query), + after_system_prompt="\n\n".join(context.after_query), + ) diff --git a/griptape/engines/rag/modules/response/prompt_response_rag_module.py b/griptape/engines/rag/modules/response/prompt_response_rag_module.py index 7b29de7ee..8552ab904 100644 --- a/griptape/engines/rag/modules/response/prompt_response_rag_module.py +++ b/griptape/engines/rag/modules/response/prompt_response_rag_module.py @@ -11,50 +11,43 @@ class PromptResponseRagModule(BaseResponseRagModule): answer_token_offset: int = field(default=400) prompt_driver: BasePromptDriver = field() - generate_system_template: Callable[[list[str], list[str], list[str]], str] = field( + generate_system_template: Callable[[RagContext, list[TextArtifact]], str] = field( default=Factory(lambda self: self.default_system_template_generator, takes_self=True) ) def run(self, context: RagContext) -> RagContext: query = context.query - before_query = context.before_query - after_query = context.after_query - text_artifact_chunks = context.text_chunks + tokenizer = self.prompt_driver.tokenizer + included_chunks = [] + system_prompt = self.generate_system_template(context, included_chunks) - if query: - tokenizer = self.prompt_driver.tokenizer - text_chunks = [] - system_prompt = self.generate_system_template(text_chunks, before_query, after_query) + for artifact in context.text_chunks: + included_chunks.append(artifact) - for artifact in text_artifact_chunks: - text_chunks.append(artifact.value) + system_prompt = self.generate_system_template(context, included_chunks) + message_token_count = self.prompt_driver.tokenizer.count_tokens( + self.prompt_driver.prompt_stack_to_string(self.generate_query_prompt_stack(system_prompt, query)) + ) - system_prompt = self.generate_system_template(text_chunks, before_query, after_query) - message_token_count = self.prompt_driver.tokenizer.count_tokens( - self.prompt_driver.prompt_stack_to_string(self.generate_query_prompt_stack(system_prompt, query)) - ) + if message_token_count + self.answer_token_offset >= tokenizer.max_input_tokens: + included_chunks.pop() - if message_token_count + self.answer_token_offset >= tokenizer.max_input_tokens: - text_chunks.pop() + system_prompt = self.generate_system_template(context, included_chunks) - system_prompt = self.generate_system_template(text_chunks, before_query, after_query) + break - break + output = self.prompt_driver.run(self.generate_query_prompt_stack(system_prompt, query)).to_artifact() - output = self.prompt_driver.run(self.generate_query_prompt_stack(system_prompt, query)).to_artifact() - - if isinstance(output, TextArtifact): - context.output = output - else: - raise ValueError("Prompt driver did not return a TextArtifact") + if isinstance(output, TextArtifact): + context.output = output + else: + raise ValueError("Prompt driver did not return a TextArtifact") return context - def default_system_template_generator( - self, text_chunks: list[str], before_system_prompt: list, after_system_prompt: list - ) -> str: + def default_system_template_generator(self, context: RagContext, artifacts: list[TextArtifact]) -> str: return J2("engines/rag/modules/response/prompt/system.j2").render( - text_chunks=text_chunks, - before_system_prompt="\n\n".join(before_system_prompt), - after_system_prompt="\n\n".join(after_system_prompt), + text_chunks=[c.to_text() for c in artifacts], + before_system_prompt="\n\n".join(context.before_query), + after_system_prompt="\n\n".join(context.after_query), ) diff --git a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py new file mode 100644 index 000000000..a37910da6 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py @@ -0,0 +1,41 @@ +from __future__ import annotations +import uuid +from typing import TYPE_CHECKING, Sequence, Any, Callable +from attrs import define, field, Factory +from griptape import utils +from griptape.artifacts import TextArtifact, ErrorArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRetrievalRagModule + +if TYPE_CHECKING: + from griptape.drivers import BaseVectorStoreDriver + from griptape.loaders import BaseTextLoader + + +@define(kw_only=True) +class TextLoaderRetrievalRagModule(BaseRetrievalRagModule): + loader: BaseTextLoader = field() + vector_store_driver: BaseVectorStoreDriver = field() + source: Any = field() + query_params: dict[str, Any] = field(factory=dict) + process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], Sequence[TextArtifact]] = field( + default=Factory(lambda: lambda es: [e.to_artifact() for e in es]) + ) + + def run(self, context: RagContext) -> Sequence[TextArtifact]: + namespace = uuid.uuid4().hex + context_source = self.get_context_param(context, "source") + source = self.source if context_source is None else context_source + + query_params = utils.dict_merge(self.query_params, self.get_context_param(context, "query_params")) + + query_params["namespace"] = namespace + + loader_output = self.loader.load(source) + + if isinstance(loader_output, ErrorArtifact): + raise Exception(loader_output.to_text() if loader_output.exception is None else loader_output.exception) + else: + self.vector_store_driver.upsert_text_artifacts({namespace: loader_output}) + + return self.process_query_output_fn(self.vector_store_driver.query(context.query, **query_params)) diff --git a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py index e91650faf..96d249693 100644 --- a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py @@ -1,6 +1,7 @@ from __future__ import annotations from typing import TYPE_CHECKING, Sequence, Any, Callable from attrs import define, field, Factory +from griptape import utils from griptape.artifacts import TextArtifact from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRetrievalRagModule @@ -18,7 +19,6 @@ class VectorStoreRetrievalRagModule(BaseRetrievalRagModule): ) def run(self, context: RagContext) -> Sequence[TextArtifact]: - context_query_params = self.get_context_param(context, "query_params") - query_params = self.query_params if context_query_params is None else context_query_params + query_params = utils.dict_merge(self.query_params, self.get_context_param(context, "query_params")) return self.process_query_output_fn(self.vector_store_driver.query(context.query, **query_params)) diff --git a/griptape/engines/rag/rag_context.py b/griptape/engines/rag/rag_context.py index ce0d1adc6..c0658ad7b 100644 --- a/griptape/engines/rag/rag_context.py +++ b/griptape/engines/rag/rag_context.py @@ -1,25 +1,35 @@ -from typing import Optional +from __future__ import annotations +from typing import Optional, TYPE_CHECKING from attrs import define, field -from griptape.artifacts import TextArtifact, BaseArtifact + +from griptape import utils +from griptape.common import Reference +from griptape.mixins import SerializableMixin + +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact, BaseArtifact @define(kw_only=True) -class RagContext: +class RagContext(SerializableMixin): """Used by RagEngine stages and module to pass context that individual modules are expected to update in the `run` method. Attributes: query: Query provided by the user. - module_params: Dictionary of dictionary parameters to be used by modules. First key should be the module name and the second a parameter name. + module_configs: Dictionary of module configs. First key should be a module name and the second a dictionary of config parameters. before_query: An optional list of strings to add before the query in generation modules. after_query: An optional list of strings to add after the query in generation modules. text_chunks: A list of text chunks to pass around from the retrieval stage to the generation stage. output: Final output from the generation stage. """ - query: str = field() - module_params: dict[str, dict] = field(factory=dict) - before_query: list[str] = field(factory=list) - after_query: list[str] = field(factory=list) - text_chunks: list[TextArtifact] = field(factory=list) - output: Optional[BaseArtifact] = field(default=None) + query: str = field(metadata={"serializable": True}) + module_configs: dict[str, dict] = field(factory=dict, metadata={"serializable": True}) + before_query: list[str] = field(factory=list, metadata={"serializable": True}) + after_query: list[str] = field(factory=list, metadata={"serializable": True}) + text_chunks: list[TextArtifact] = field(factory=list, metadata={"serializable": True}) + output: Optional[BaseArtifact] = field(default=None, metadata={"serializable": True}) + + def get_references(self) -> list[Reference]: + return utils.references_from_artifacts(self.text_chunks) diff --git a/griptape/loaders/base_text_loader.py b/griptape/loaders/base_text_loader.py index c2840d62f..4f2a93183 100644 --- a/griptape/loaders/base_text_loader.py +++ b/griptape/loaders/base_text_loader.py @@ -1,13 +1,11 @@ from __future__ import annotations - -from abc import ABC +from abc import ABC, abstractmethod from typing import Any, Optional, Union, cast - from attrs import define, field, Factory - from griptape.artifacts import TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact from griptape.chunkers import TextChunker, BaseChunker +from griptape.common import Reference from griptape.drivers import BaseEmbeddingDriver from griptape.loaders import BaseLoader from griptape.tokenizers import OpenAiTokenizer @@ -32,6 +30,10 @@ class BaseTextLoader(BaseLoader, ABC): ) embedding_driver: Optional[BaseEmbeddingDriver] = field(default=None, kw_only=True) encoding: str = field(default="utf-8", kw_only=True) + reference: Optional[Reference] = field(default=None, kw_only=True) + + @abstractmethod + def load(self, source: Any, *args, **kwargs) -> ErrorArtifact | list[TextArtifact]: ... def load_collection(self, sources: list[Any], *args, **kwargs) -> dict[str, ErrorArtifact | list[TextArtifact]]: return cast( @@ -43,12 +45,14 @@ def _text_to_artifacts(self, text: str) -> list[TextArtifact]: chunks = self.chunker.chunk(text) if self.chunker else [TextArtifact(text)] - if self.embedding_driver: - for chunk in chunks: + for chunk in chunks: + if self.embedding_driver: chunk.generate_embedding(self.embedding_driver) - for chunk in chunks: + chunk.reference = self.reference + chunk.encoding = self.encoding + artifacts.append(chunk) return artifacts diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 976a9ea5b..0d135bcbd 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -52,7 +52,7 @@ def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifac result = self.rag_engine.process( RagContext( query=query, - module_params={ + module_configs={ self.retrieval_rag_module_name: { "query_params": { "namespace": namespace, diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 1099e1bf7..e199a5c7e 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -59,7 +59,7 @@ def _get_field_for_type(cls, field_type: type) -> fields.Field | fields.Nested: if ABC in field_class.__bases__: return fields.Nested(PolymorphicSchema(inner_class=field_class), allow_none=optional) else: - return fields.Nested(cls.from_attrs_cls(field_type), allow_none=optional) + return fields.Nested(cls.from_attrs_cls(field_class), allow_none=optional) elif cls.is_list_sequence(field_class): if args: return fields.List(cls_or_instance=cls._get_field_for_type(args[0]), allow_none=optional) @@ -105,9 +105,10 @@ def _resolve_types(cls, attrs_cls: type) -> None: # These modules are required to avoid `NameError`s when resolving types. from griptape.drivers import BaseConversationMemoryDriver, BasePromptDriver from griptape.structures import Structure - from griptape.common import PromptStack, Message + from griptape.common import PromptStack, Message, Reference from griptape.tokenizers.base_tokenizer import BaseTokenizer from typing import Any + from griptape.artifacts import BaseArtifact boto3 = import_optional_dependency("boto3") if is_dependency_installed("boto3") else Any Client = import_optional_dependency("cohere").Client if is_dependency_installed("cohere") else Any @@ -123,6 +124,8 @@ def _resolve_types(cls, attrs_cls: type) -> None: "BaseTokenizer": BaseTokenizer, "boto3": boto3, "Client": Client, + "Reference": Reference, + "BaseArtifact": BaseArtifact, }, ) diff --git a/griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 b/griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 new file mode 100644 index 000000000..0dcf60fd4 --- /dev/null +++ b/griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 @@ -0,0 +1,37 @@ +You are an expert Q&A system. Always answer the question using the provided context information, and not prior knowledge. Always be truthful. Don't make up facts. +{% if before_system_prompt %} +{{ before_system_prompt }} + +{% endif %} +Use the following list of excerpts to respond. If there are no excerpts available or excerpts don't have relevant information respond with "I could not find an answer." + +When responding to a question, always reference facts from excerpts whenever possible. Some excerpts might have references associated with them. When referencing facts from excerpts always add a footnote number in square brackets after that fact. At the end of your response compile a list of footnotes. Always include a reference title and other available reference information. Make sure footnotes are unique and have no duplicates. +{% if references|length > 0 %} + +## References + +{% for reference in references %} +{{ reference }} +{% endfor %} +{% endif %} +{% if text_chunk_artifacts|length > 0 %} + +## Excerpts + +{% for artifact in text_chunk_artifacts %} +{% if artifact.reference %} +Excerpt (Reference ID: {{ artifact.reference.id }}): """ +{{ artifact.to_text() }} +{% else %} +Excerpt: """ +{{ artifact.to_text() }} +{% endif %} +""" +{% endfor %} +{% if after_system_prompt %} + +{{ after_system_prompt }} +{% endif %} +{% else %} +No excerpt available. +{% endif %} \ No newline at end of file diff --git a/griptape/templates/engines/rag/modules/response/prompt/system.j2 b/griptape/templates/engines/rag/modules/response/prompt/system.j2 index 4b06f3e8c..1fa9d8c12 100644 --- a/griptape/templates/engines/rag/modules/response/prompt/system.j2 +++ b/griptape/templates/engines/rag/modules/response/prompt/system.j2 @@ -1,11 +1,14 @@ +You are an expert Q&A system. Always answer the question using the provided context information, and not prior knowledge. Always be truthful. Don't make up facts. You can answer questions by searching through text chunks. {% if before_system_prompt %} {{ before_system_prompt }} {% endif %} -Always be truthful. Don't make up facts. You can answer questions by searching through text chunks. Use the following list of text chunks to respond. If there are no text chunks available or text chunks don't have relevant information respond with "I could not find an answer." +Use the following list of text chunks to respond. If there are no text chunks available or text chunks don't have relevant information respond with "I could not find an answer." {% if text_chunks and text_chunks|length > 0 %} +## Text Chunks {% for chunk in text_chunks %} + Text chunk: """ {{ chunk }} """ diff --git a/griptape/utils/__init__.py b/griptape/utils/__init__.py index a84703f39..ceb19547e 100644 --- a/griptape/utils/__init__.py +++ b/griptape/utils/__init__.py @@ -17,6 +17,7 @@ from .load_artifact_from_memory import load_artifact_from_memory from .deprecation import deprecation_warn from .structure_visualizer import StructureVisualizer +from .reference_utils import references_from_artifacts def minify_json(value: str) -> str: @@ -45,4 +46,5 @@ def minify_json(value: str) -> str: "load_file", "load_files", "StructureVisualizer", + "references_from_artifacts", ] diff --git a/griptape/utils/dict_utils.py b/griptape/utils/dict_utils.py index c5f6bb676..a396bf7d1 100644 --- a/griptape/utils/dict_utils.py +++ b/griptape/utils/dict_utils.py @@ -1,3 +1,6 @@ +from typing import Optional + + def remove_null_values_in_dict_recursively(d: dict) -> dict: if isinstance(d, dict): return {k: remove_null_values_in_dict_recursively(v) for k, v in d.items() if v is not None} @@ -5,7 +8,7 @@ def remove_null_values_in_dict_recursively(d: dict) -> dict: return d -def dict_merge(dct: dict, merge_dct: dict, add_keys: bool = True) -> dict: +def dict_merge(dct: Optional[dict], merge_dct: Optional[dict], add_keys: bool = True) -> dict: """Recursive dict merge. Inspired by :meth:``dict.update()``, instead of updating only top-level keys, dict_merge recurses down into dicts nested to an arbitrary depth, updating keys. The ``merge_dct`` is merged into @@ -26,7 +29,11 @@ def dict_merge(dct: dict, merge_dct: dict, add_keys: bool = True) -> dict: Returns: dict: updated dict """ + dct = {} if dct is None else dct + merge_dct = {} if merge_dct is None else merge_dct + dct = dct.copy() + if not add_keys: merge_dct = {k: merge_dct[k] for k in set(dct).intersection(set(merge_dct))} diff --git a/griptape/utils/reference_utils.py b/griptape/utils/reference_utils.py new file mode 100644 index 000000000..761ee3d24 --- /dev/null +++ b/griptape/utils/reference_utils.py @@ -0,0 +1,12 @@ +from griptape.artifacts import TextArtifact +from griptape.common import Reference + + +def references_from_artifacts(artifacts: list[TextArtifact]) -> list[Reference]: + references = [] + + for a in artifacts: + if a.reference is not None and a.reference not in references: + references.append(a.reference) + + return references diff --git a/tests/mocks/mock_serializable.py b/tests/mocks/mock_serializable.py index 4de173b07..b02c071aa 100644 --- a/tests/mocks/mock_serializable.py +++ b/tests/mocks/mock_serializable.py @@ -5,7 +5,12 @@ @define class MockSerializable(SerializableMixin): + @define + class NestedMockSerializable(SerializableMixin): + foo: str = field(default="bar", kw_only=True, metadata={"serializable": True}) + foo: str = field(default="bar", kw_only=True, metadata={"serializable": True}) bar: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) baz: Optional[list[int]] = field(default=None, kw_only=True, metadata={"serializable": True}) secret: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) + nested: Optional[NestedMockSerializable] = field(default=None, kw_only=True, metadata={"serializable": True}) diff --git a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py index df0ca4d3c..ba79a4def 100644 --- a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py @@ -72,7 +72,7 @@ def test_store_with_sort_key(self): value_attribute_key=self.VALUE_ATTRIBUTE_KEY, partition_key_value=self.PARTITION_KEY_VALUE, sort_key="sortKey", - sort_key_value="foo" + sort_key_value="foo", ) memory = ConversationMemory(driver=memory_driver) pipeline = Pipeline(prompt_driver=prompt_driver, conversation_memory=memory) @@ -120,7 +120,7 @@ def test_load_with_sort_key(self): value_attribute_key=self.VALUE_ATTRIBUTE_KEY, partition_key_value=self.PARTITION_KEY_VALUE, sort_key="sortKey", - sort_key_value="foo" + sort_key_value="foo", ) memory = ConversationMemory(driver=memory_driver) pipeline = Pipeline(prompt_driver=prompt_driver, conversation_memory=memory) @@ -135,4 +135,4 @@ def test_load_with_sort_key(self): assert new_memory.type == "ConversationMemory" assert len(new_memory.runs) == 2 assert new_memory.runs[0].input.value == "test" - assert new_memory.runs[0].output.value == "mock output" \ No newline at end of file + assert new_memory.runs[0].output.value == "mock output" diff --git a/tests/unit/drivers/rerank/test_cohere_rerank_driver.py b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py index f7b050551..952546e5a 100644 --- a/tests/unit/drivers/rerank/test_cohere_rerank_driver.py +++ b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py @@ -1,5 +1,5 @@ -from unittest.mock import Mock import pytest +from cohere import RerankResponseResultsItemDocument, RerankResponseResultsItem from griptape.artifacts import TextArtifact from griptape.drivers import CohereRerankDriver @@ -8,7 +8,14 @@ class TestCohereRerankDriver: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value - mock_client.rerank.return_value.results = [Mock(), Mock()] + mock_client.rerank.return_value.results = [ + RerankResponseResultsItem( + index=1, relevance_score=1.0, document=RerankResponseResultsItemDocument(text="foo") + ), + RerankResponseResultsItem( + index=2, relevance_score=0.5, document=RerankResponseResultsItemDocument(text="bar") + ), + ] return mock_client diff --git a/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py b/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py deleted file mode 100644 index cb8fcbefe..000000000 --- a/tests/unit/drivers/vector/test_in_memory_local_vector_store_driver.py +++ /dev/null @@ -1,10 +0,0 @@ -import pytest -from griptape.drivers import LocalVectorStoreDriver -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.unit.drivers.vector.test_base_local_vector_store_driver import BaseLocalVectorStoreDriver - - -class TestInMemoryLocalVectorStoreDriver(BaseLocalVectorStoreDriver): - @pytest.fixture - def driver(self): - return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) diff --git a/tests/unit/drivers/vector/test_local_vector_store_driver.py b/tests/unit/drivers/vector/test_local_vector_store_driver.py new file mode 100644 index 000000000..937f14ece --- /dev/null +++ b/tests/unit/drivers/vector/test_local_vector_store_driver.py @@ -0,0 +1,23 @@ +import pytest +from griptape.artifacts import TextArtifact +from griptape.drivers import LocalVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.unit.drivers.vector.test_base_local_vector_store_driver import BaseLocalVectorStoreDriver + + +class TestLocalVectorStoreDriver(BaseLocalVectorStoreDriver): + @pytest.fixture + def driver(self): + return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + + def test_upsert_text_artifacts_dict(self, driver): + driver.upsert_text_artifacts({"foo": [TextArtifact("bar"), TextArtifact("baz")], "bar": [TextArtifact("bar")]}) + + assert len(driver.load_artifacts("foo")) == 2 + assert len(driver.load_artifacts("bar")) == 1 + + def test_upsert_text_artifacts_list(self, driver): + driver.upsert_text_artifacts([TextArtifact("bar"), TextArtifact("baz")]) + + assert len(driver.load_artifacts("foo")) == 0 + assert len(driver.load_artifacts()) == 2 diff --git a/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py new file mode 100644 index 000000000..e5ba50a5b --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py @@ -0,0 +1,33 @@ +import pytest +from griptape.artifacts import TextArtifact +from griptape.common import Reference +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import FootnotePromptResponseRagModule +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestFootnotePromptResponseRagModule: + @pytest.fixture + def module(self): + return FootnotePromptResponseRagModule(prompt_driver=MockPromptDriver()) + + def test_run(self, module): + assert module.run(RagContext(query="test")).output.value == "mock output" + + def test_prompt(self, module): + system_message = module.default_system_template_generator( + RagContext(query="test", before_query=["*RULESET*", "*META*"]), + artifacts=[ + TextArtifact("*TEXT SEGMENT 1*", reference=Reference(title="source 1")), + TextArtifact("*TEXT SEGMENT 2*", reference=Reference(title="source 2")), + TextArtifact("*TEXT SEGMENT 3*"), + ], + ) + + assert "*RULESET*" in system_message + assert "*META*" in system_message + assert "*TEXT SEGMENT 1*" in system_message + assert "*TEXT SEGMENT 2*" in system_message + assert "*TEXT SEGMENT 3*" in system_message + assert "source 1" in system_message + assert "source 2" in system_message diff --git a/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py index 43927bd8a..9519c8017 100644 --- a/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py +++ b/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py @@ -6,7 +6,9 @@ class TestMetadataBeforeResponseRagModule: def test_run(self): module = MetadataBeforeResponseRagModule(name="foo") - assert "foo" in module.run(RagContext(module_params={"foo": {"metadata": "foo"}}, query="test")).before_query[0] + assert ( + "foo" in module.run(RagContext(module_configs={"foo": {"metadata": "foo"}}, query="test")).before_query[0] + ) def test_run_with_override(self): module = MetadataBeforeResponseRagModule(name="foo", metadata="bar") @@ -14,6 +16,6 @@ def test_run_with_override(self): assert ( "bar" in module.run( - RagContext(module_params={"foo": {"query_params": {"metadata": "foo"}}}, query="test") + RagContext(module_configs={"foo": {"query_params": {"metadata": "foo"}}}, query="test") ).before_query[0] ) diff --git a/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py index d8835bbe4..f262d6d06 100644 --- a/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py +++ b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py @@ -1,4 +1,5 @@ import pytest +from griptape.artifacts import TextArtifact from griptape.engines.rag import RagContext from griptape.engines.rag.modules import PromptResponseRagModule from tests.mocks.mock_prompt_driver import MockPromptDriver @@ -14,9 +15,8 @@ def test_run(self, module): def test_prompt(self, module): system_message = module.default_system_template_generator( - text_chunks=["*TEXT SEGMENT 1*", "*TEXT SEGMENT 2*"], - before_system_prompt=["*RULESET*", "*META*"], - after_system_prompt=[], + RagContext(query="test", before_query=["*RULESET*", "*META*"], after_query=[]), + artifacts=[TextArtifact("*TEXT SEGMENT 1*"), TextArtifact("*TEXT SEGMENT 2*")], ) assert "*RULESET*" in system_message diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py index 838f02e37..fa3bfecb2 100644 --- a/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py +++ b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py @@ -1,5 +1,6 @@ -from unittest.mock import Mock import pytest +from cohere import RerankResponseResultsItem, RerankResponseResultsItemDocument +from griptape.artifacts import TextArtifact from griptape.drivers import CohereRerankDriver from griptape.engines.rag import RagContext from griptape.engines.rag.modules import TextChunksRerankRagModule @@ -9,12 +10,19 @@ class TestTextChunksRerankRagModule: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value - mock_client.rerank.return_value.results = [Mock(), Mock()] + mock_client.rerank.return_value.results = [ + RerankResponseResultsItem( + index=1, relevance_score=1.0, document=RerankResponseResultsItemDocument(text="foo") + ), + RerankResponseResultsItem( + index=2, relevance_score=0.5, document=RerankResponseResultsItemDocument(text="bar") + ), + ] return mock_client def test_run(self, mock_client): module = TextChunksRerankRagModule(rerank_driver=CohereRerankDriver(api_key="api-key")) - result = module.run(RagContext(query="test")) + result = module.run(RagContext(query="test", text_chunks=[TextArtifact("foo"), TextArtifact("bar")])) assert len(result) == 2 diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py new file mode 100644 index 000000000..7c69f674a --- /dev/null +++ b/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py @@ -0,0 +1,26 @@ +import pytest + +from griptape.drivers import LocalVectorStoreDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import TextLoaderRetrievalRagModule +from griptape.loaders import WebLoader +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver + +MAX_TOKENS = 50 + + +class TestTextLoaderRetrievalRagModule: + @pytest.fixture(autouse=True) + def mock_trafilatura_fetch_url(self, mocker): + mocker.patch("trafilatura.fetch_url", return_value="foobar") + + def test_run(self): + embedding_driver = MockEmbeddingDriver() + + module = TextLoaderRetrievalRagModule( + loader=WebLoader(max_tokens=MAX_TOKENS, embedding_driver=embedding_driver), + vector_store_driver=LocalVectorStoreDriver(embedding_driver=embedding_driver), + source="https://www.griptape.ai", + ) + + assert module.run(RagContext(query="foo"))[0].value == "foobar" diff --git a/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py index 3a01b3eaa..9fecc3c0e 100644 --- a/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py +++ b/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py @@ -1,4 +1,5 @@ from griptape.artifacts import TextArtifact +from griptape.common import Reference from griptape.drivers import LocalVectorStoreDriver from griptape.engines.rag import RagContext from griptape.engines.rag.modules import VectorStoreRetrievalRagModule @@ -10,7 +11,9 @@ def test_run_without_namespace(self): vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) module = VectorStoreRetrievalRagModule(vector_store_driver=vector_store_driver) - vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") + vector_store_driver.upsert_text_artifact( + TextArtifact("foobar1", reference=Reference(title="boo")), namespace="test" + ) vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") result = module.run(RagContext(query="test")) @@ -45,13 +48,13 @@ def test_run_with_namespace_overrides(self): result1 = module.run( RagContext( - query="test", module_params={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "empty"}}} + query="test", module_configs={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "empty"}}} ) ) result2 = module.run( RagContext( - query="test", module_params={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "test"}}} + query="test", module_configs={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "test"}}} ) ) diff --git a/tests/unit/engines/rag/modules/test_base_rag_nodule.py b/tests/unit/engines/rag/modules/test_base_rag_nodule.py index 0fc415e0e..be1fda861 100644 --- a/tests/unit/engines/rag/modules/test_base_rag_nodule.py +++ b/tests/unit/engines/rag/modules/test_base_rag_nodule.py @@ -14,7 +14,7 @@ def test_get_context_param(self): module = MockRagModule(name="boo") context = RagContext(query="test") - context.module_params["boo"] = {"foo": "bar"} + context.module_configs["boo"] = {"foo": "bar"} assert module.get_context_param(context, "foo") == "bar" @@ -24,4 +24,4 @@ def test_set_context_param(self): module.set_context_param(context, "foo", "bar") - assert context.module_params["boo"]["foo"] == "bar" + assert context.module_configs["boo"]["foo"] == "bar" diff --git a/tests/unit/engines/rag/test_rag_context.py b/tests/unit/engines/rag/test_rag_context.py new file mode 100644 index 000000000..7eba86683 --- /dev/null +++ b/tests/unit/engines/rag/test_rag_context.py @@ -0,0 +1,23 @@ +from griptape.artifacts import TextArtifact +from griptape.common import Reference +from griptape.engines.rag import RagContext + + +class TestRagContext: + def test_get_references(self): + reference1 = Reference(title="foo") + reference2 = Reference(title="bar") + context = RagContext( + query="foo", + text_chunks=[ + TextArtifact("foo", reference=reference1), + TextArtifact("foo", reference=reference1), + TextArtifact("foo"), + TextArtifact("foo", reference=reference2), + ], + ) + references = context.get_references() + + assert len(references) == 2 + assert references[0].id == reference1.id + assert references[1].id == reference2.id diff --git a/tests/unit/mixins/test_seriliazable_mixin.py b/tests/unit/mixins/test_seriliazable_mixin.py index d733d7858..1704000e3 100644 --- a/tests/unit/mixins/test_seriliazable_mixin.py +++ b/tests/unit/mixins/test_seriliazable_mixin.py @@ -23,16 +23,22 @@ def test_from_json(self): def test_str(self): assert str(MockSerializable()) == json.dumps( - {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None} + {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None, "nested": None} ) def test_to_json(self): assert MockSerializable().to_json() == json.dumps( - {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None} + {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None, "nested": None} ) def test_to_dict(self): - assert MockSerializable().to_dict() == {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None} + assert MockSerializable().to_dict() == { + "type": "MockSerializable", + "foo": "bar", + "bar": None, + "baz": None, + "nested": None, + } def test_import_class_rec(self): assert ( @@ -47,3 +53,8 @@ def test_import_class_rec(self): with pytest.raises(ValueError): MockSerializable._import_cls_rec("griptape.memory.task", "ConversationMemory") + + def test_nested_optional_serializable(self): + assert MockSerializable(nested=None).to_dict().get("nested") is None + + assert MockSerializable(nested=MockSerializable.NestedMockSerializable()).to_dict()["nested"]["foo"] == "bar" diff --git a/tests/unit/utils/test_dict_utils.py b/tests/unit/utils/test_dict_utils.py index ba6d5470d..958e0295b 100644 --- a/tests/unit/utils/test_dict_utils.py +++ b/tests/unit/utils/test_dict_utils.py @@ -10,7 +10,7 @@ def test_remove_null_values_in_dict_recursively(self): assert remove_null_values_in_dict_recursively(dict_with_nones) == dict_without_nones - def test_merges_dicts(self): + def test_dict_merge_merges_dicts(self): a = {"a": 1, "b": {"b1": 2, "b2": 3}} b = {"a": 1, "b": {"b1": 4}} @@ -18,7 +18,22 @@ def test_merges_dicts(self): assert dict_merge(a, b)["b"]["b2"] == 3 assert dict_merge(a, b)["b"]["b1"] == 4 - def test_inserts_new_keys(self): + def test_dict_merge_works_with_optionals(self): + a = {"a": 1, "b": {"b1": 2, "b2": 3}} + b = None + + assert dict_merge(a, b)["a"] == 1 + assert dict_merge(a, b)["b"]["b2"] == 3 + assert dict_merge(a, b)["b"]["b1"] == 2 + + a = None + b = {"a": 1, "b": {"b1": 2, "b2": 3}} + + assert dict_merge(a, b)["a"] == 1 + assert dict_merge(a, b)["b"]["b2"] == 3 + assert dict_merge(a, b)["b"]["b1"] == 2 + + def test_dict_merge_inserts_new_keys(self): a = {"a": 1, "b": {"b1": 2, "b2": 3}} b = {"a": 1, "b": {"b1": 4, "b3": 5}, "c": 6} @@ -28,7 +43,7 @@ def test_inserts_new_keys(self): assert dict_merge(a, b)["b"]["b3"] == 5 assert dict_merge(a, b)["c"] == 6 - def test_does_not_insert_new_keys(self): + def test_dict_merge_does_not_insert_new_keys(self): a = {"a": 1, "b": {"b1": 2, "b2": 3}} b = {"a": 1, "b": {"b1": 4, "b3": 5}, "c": 6} diff --git a/tests/utils/test_reference_utils.py b/tests/utils/test_reference_utils.py new file mode 100644 index 000000000..c3491f5d0 --- /dev/null +++ b/tests/utils/test_reference_utils.py @@ -0,0 +1,22 @@ +from griptape.artifacts import TextArtifact +from griptape.common import Reference +from griptape.engines.rag.modules import PromptResponseRagModule +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestReferenceUtils: + def test_references_from_artifacts(self): + module = PromptResponseRagModule(prompt_driver=MockPromptDriver()) + reference1 = Reference(title="foo") + reference2 = Reference(title="bar") + artifacts = [ + TextArtifact("foo", reference=reference1), + TextArtifact("foo", reference=reference1), + TextArtifact("foo"), + TextArtifact("foo", reference=reference2), + ] + references = module.references_from_artifacts(artifacts) + + assert len(references) == 2 + assert references[0].id == reference1.id + assert references[1].id == reference2.id From bb158eae9ec106facc2e11164552a9c778981006 Mon Sep 17 00:00:00 2001 From: Zach Giordano <32624672+zachgiordano@users.noreply.github.com> Date: Mon, 8 Jul 2024 16:21:34 -0400 Subject: [PATCH 43/87] Update certifi (#944) Co-authored-by: Collin Dutter --- poetry.lock | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/poetry.lock b/poetry.lock index 83d2d5632..da5b152d2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -757,13 +757,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, ] [[package]] @@ -3466,6 +3466,7 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ + {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4abe7fef64914ccfa909bc2ba39739670ecc9e820c83ccc7a6ed414122599b83"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1"}, ] @@ -4709,7 +4710,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -4717,15 +4717,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -4742,7 +4735,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -4750,7 +4742,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, From c9b92ea3109cbe936091d3640921dde0a82a92a9 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 9 Jul 2024 09:58:53 -0700 Subject: [PATCH 44/87] Fix azure streaming (#946) --- griptape/drivers/prompt/azure_openai_chat_prompt_driver.py | 6 +++++- griptape/drivers/prompt/openai_chat_prompt_driver.py | 5 ++--- .../drivers/prompt/test_azure_openai_chat_prompt_driver.py | 7 +------ 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py index 50e9effe6..64145b1a9 100644 --- a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py @@ -44,6 +44,10 @@ class AzureOpenAiChatPromptDriver(OpenAiChatPromptDriver): def _base_params(self, prompt_stack: PromptStack) -> dict: params = super()._base_params(prompt_stack) # TODO: Add `seed` parameter once Azure supports it. - del params["seed"] + if "seed" in params: + del params["seed"] + # TODO: Add `stream_options` parameter once Azure supports it. + if "stream_options" in params: + del params["stream_options"] return params diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index e1e046d11..a89b4eb57 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -90,9 +90,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: raise Exception("Completion with more than one choice is not supported yet.") def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: - result = self.client.chat.completions.create( - **self._base_params(prompt_stack), stream=True, stream_options={"include_usage": True} - ) + result = self.client.chat.completions.create(**self._base_params(prompt_stack), stream=True) for chunk in result: if chunk.usage is not None: @@ -124,6 +122,7 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "seed": self.seed, **({"stop": self.tokenizer.stop_sequences} if self.tokenizer.stop_sequences else {}), **({"max_tokens": self.max_tokens} if self.max_tokens is not None else {}), + **({"stream_options": {"include_usage": True}} if self.stream else {}), } if self.response_format == "json_object": diff --git a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py index 92544a74e..378ecc3da 100644 --- a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py @@ -57,12 +57,7 @@ def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, # Then mock_chat_completion_stream_create.assert_called_once_with( - model=driver.model, - temperature=driver.temperature, - user=driver.user, - stream=True, - messages=messages, - stream_options={"include_usage": True}, + model=driver.model, temperature=driver.temperature, user=driver.user, stream=True, messages=messages ) assert event.content.text == "model-output" From b7ee2eea77341225dc6e4690b3b478d4416c8fd9 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 9 Jul 2024 11:55:21 -0700 Subject: [PATCH 45/87] Release/v0.28.0 (#947) Co-authored-by: dylanholmes <4370153+dylanholmes@users.noreply.github.com> Co-authored-by: CJ Kindel Co-authored-by: Andrew French Co-authored-by: Vasily Vasinov Co-authored-by: Matt Vallillo Co-authored-by: Michal Co-authored-by: Zach Giordano <32624672+zachgiordano@users.noreply.github.com> Co-authored-by: Ikko Eltociear Ashimine Co-authored-by: torabshaikh Co-authored-by: Aodhan Roche Co-authored-by: Kyle Roche Co-authored-by: Emily Danielson <2302515+emjay07@users.noreply.github.com> Co-authored-by: hkhajgiwale Co-authored-by: Harsh Khajgiwale <13365920+hkhajgiwale@users.noreply.github.com> Co-authored-by: Anush Co-authored-by: datashaman --- .github/pull_request_template.md | 5 + .github/workflows/code-checks.yml | 13 + .github/workflows/docs-integration-tests.yml | 3 + .pre-commit-config.yaml | 7 + CHANGELOG.md | 86 ++- Makefile | 14 +- README.md | 32 +- _typos.toml | 8 + docs/examples/load-query-and-chat-marqo.md | 7 +- docs/examples/multi-agent-workflow.md | 8 +- docs/examples/multiple-agent-shared-memory.md | 6 +- docs/examples/query-webpage.md | 2 +- docs/examples/talk-to-a-pdf.md | 52 +- docs/examples/talk-to-a-webpage.md | 43 +- docs/griptape-framework/data/artifacts.md | 19 +- docs/griptape-framework/data/index.md | 12 +- .../drivers/audio-transcription-drivers.md | 2 + .../drivers/conversation-memory-drivers.md | 3 + .../drivers/image-generation-drivers.md | 2 + .../drivers/image-query-drivers.md | 16 +- .../drivers/prompt-drivers.md | 30 +- .../griptape-framework/drivers/sql-drivers.md | 8 +- .../drivers/structure-run-drivers.md | 6 +- .../drivers/text-to-speech-drivers.md | 2 + .../drivers/vector-store-drivers.md | 97 +++- .../drivers/web-scraper-drivers.md | 36 +- .../drivers/web-search-drivers.md | 62 +++ .../engines/image-query-engines.md | 25 + .../engines/query-engines.md | 52 -- .../griptape-framework/engines/rag-engines.md | 72 +++ .../engines/summary-engines.md | 2 +- docs/griptape-framework/misc/events.md | 8 +- docs/griptape-framework/misc/tokenizers.md | 2 +- docs/griptape-framework/structures/agents.md | 2 +- docs/griptape-framework/structures/config.md | 23 +- .../structures/task-memory.md | 116 ++-- docs/griptape-framework/structures/tasks.md | 113 ++-- .../official-tools/date-time.md | 4 +- .../official-tools/rag-client.md | 51 ++ .../official-tools/vector-store-client.md | 25 +- .../official-tools/web-search.md | 13 +- griptape/artifacts/__init__.py | 2 + griptape/artifacts/base_artifact.py | 14 +- griptape/artifacts/boolean_artifact.py | 30 + griptape/artifacts/media_artifact.py | 2 +- griptape/chunkers/base_chunker.py | 5 +- griptape/common/__init__.py | 26 + .../query => common/prompt_stack}/__init__.py | 0 .../common/prompt_stack/contents}/__init__.py | 0 .../contents/base_delta_message_content.py | 12 + .../contents/base_message_content.py | 30 + .../contents/image_message_content.py | 17 + .../contents/text_delta_message_content.py | 9 + .../contents/text_message_content.py | 20 + .../common/prompt_stack/messages/__init__.py | 0 .../prompt_stack/messages/base_message.py | 44 ++ .../prompt_stack/messages/delta_message.py | 15 + .../common/prompt_stack/messages/message.py | 38 ++ griptape/common/prompt_stack/prompt_stack.py | 56 ++ griptape/common/reference.py | 14 + .../config/amazon_bedrock_structure_config.py | 55 +- griptape/config/google_structure_config.py | 4 +- griptape/drivers/__init__.py | 16 + .../base_event_listener_driver.py | 11 +- .../amazon_s3_file_manager_driver.py | 2 +- .../file_manager/base_file_manager_driver.py | 9 +- .../amazon_bedrock_image_generation_driver.py | 2 +- .../amazon_bedrock_image_query_driver.py | 2 +- ...zon_dynamodb_conversation_memory_driver.py | 14 +- .../prompt/amazon_bedrock_prompt_driver.py | 78 ++- ...mazon_sagemaker_jumpstart_prompt_driver.py | 61 ++- .../drivers/prompt/anthropic_prompt_driver.py | 117 ++-- .../prompt/azure_openai_chat_prompt_driver.py | 8 +- griptape/drivers/prompt/base_prompt_driver.py | 118 ++-- .../drivers/prompt/cohere_prompt_driver.py | 84 ++- .../drivers/prompt/dummy_prompt_driver.py | 17 +- .../drivers/prompt/google_prompt_driver.py | 108 ++-- .../prompt/huggingface_hub_prompt_driver.py | 43 +- .../huggingface_pipeline_prompt_driver.py | 44 +- .../drivers/prompt/ollama_prompt_driver.py | 38 +- .../prompt/openai_chat_prompt_driver.py | 129 +++-- griptape/drivers/rerank/__init__.py | 0 griptape/drivers/rerank/base_rerank_driver.py | 9 + .../drivers/rerank/cohere_rerank_driver.py | 32 ++ .../azure_mongodb_vector_store_driver.py | 4 +- .../vector/base_vector_store_driver.py | 118 ++-- .../vector/dummy_vector_store_driver.py | 2 +- .../vector/local_vector_store_driver.py | 69 ++- .../vector/marqo_vector_store_driver.py | 16 +- .../mongodb_atlas_vector_store_driver.py | 9 +- .../vector/opensearch_vector_store_driver.py | 6 +- .../vector/pgvector_vector_store_driver.py | 4 +- .../vector/pinecone_vector_store_driver.py | 4 +- .../vector/qdrant_vector_store_driver.py | 207 +++++++ .../vector/redis_vector_store_driver.py | 9 +- .../markdownify_web_scraper_driver.py | 67 ++- .../web_scraper/proxy_web_scraper_driver.py | 17 + griptape/drivers/web_search/__init__.py | 0 .../web_search/base_web_search_driver.py | 14 + .../duck_duck_go_web_search_driver.py | 29 + .../web_search/google_web_search_driver.py | 39 ++ griptape/engines/__init__.py | 4 - .../extraction/csv_extraction_engine.py | 11 +- .../extraction/json_extraction_engine.py | 11 +- griptape/engines/query/base_query_engine.py | 29 - griptape/engines/query/vector_query_engine.py | 95 ---- griptape/engines/rag/__init__.py | 4 + griptape/engines/rag/modules/__init__.py | 33 ++ .../engines/rag/modules/base_rag_module.py | 28 + .../engines/rag/modules/query/__init__.py | 0 .../modules/query/base_query_rag_module.py | 10 + .../engines/rag/modules/response/__init__.py | 0 .../base_after_response_rag_module.py | 10 + .../base_before_response_rag_module.py | 10 + .../response/base_response_rag_module.py | 10 + .../footnote_prompt_response_rag_module.py | 18 + .../metadata_before_response_rag_module.py | 19 + .../response/prompt_response_rag_module.py | 53 ++ .../rulesets_before_response_rag_module.py | 15 + .../text_chunks_response_rag_module.py | 12 + .../engines/rag/modules/retrieval/__init__.py | 0 .../retrieval/base_rerank_rag_module.py | 16 + .../retrieval/base_retrieval_rag_module.py | 12 + .../text_chunks_rerank_rag_module.py | 12 + .../text_loader_retrieval_rag_module.py | 41 ++ .../vector_store_retrieval_rag_module.py | 24 + griptape/engines/rag/rag_context.py | 35 ++ griptape/engines/rag/rag_engine.py | 43 ++ griptape/engines/rag/stages/__init__.py | 6 + griptape/engines/rag/stages/base_rag_stage.py | 20 + .../engines/rag/stages/query_rag_stage.py | 23 + .../engines/rag/stages/response_rag_stage.py | 46 ++ .../engines/rag/stages/retrieval_rag_stage.py | 59 ++ .../engines/summary/prompt_summary_engine.py | 24 +- griptape/events/base_prompt_event.py | 1 - griptape/events/finish_prompt_event.py | 3 + griptape/events/start_prompt_event.py | 3 +- griptape/loaders/base_loader.py | 17 +- griptape/loaders/base_text_loader.py | 23 +- griptape/loaders/sql_loader.py | 5 +- .../structure/base_conversation_memory.py | 18 +- .../memory/structure/conversation_memory.py | 6 +- griptape/memory/structure/run.py | 5 +- .../structure/summary_conversation_memory.py | 12 +- .../task/storage/base_artifact_storage.py | 2 +- .../task/storage/blob_artifact_storage.py | 2 +- .../task/storage/text_artifact_storage.py | 55 +- griptape/memory/task/task_memory.py | 2 +- griptape/mixins/rule_mixin.py | 5 +- griptape/mixins/serializable_mixin.py | 2 +- griptape/schemas/base_schema.py | 9 +- griptape/schemas/polymorphic_schema.py | 8 +- griptape/structures/agent.py | 27 +- griptape/structures/pipeline.py | 9 +- griptape/structures/structure.py | 48 +- griptape/structures/workflow.py | 27 +- griptape/tasks/__init__.py | 4 +- griptape/tasks/actions_subtask.py | 19 +- griptape/tasks/base_task.py | 8 +- griptape/tasks/prompt_task.py | 67 ++- griptape/tasks/rag_task.py | 31 ++ griptape/tasks/text_query_task.py | 35 -- griptape/tasks/toolkit_task.py | 12 +- .../response/footnote_prompt/system.j2 | 37 ++ .../rag/modules/response/metadata/system.j2 | 5 + .../rag/modules/response/prompt/system.j2 | 22 + .../tokenizers/amazon_bedrock_tokenizer.py | 1 + griptape/tokenizers/base_tokenizer.py | 3 +- griptape/tokenizers/huggingface_tokenizer.py | 1 + griptape/tokenizers/openai_tokenizer.py | 7 +- griptape/tokenizers/voyageai_tokenizer.py | 7 +- griptape/tools/__init__.py | 2 + griptape/tools/base_tool.py | 6 +- .../tool.py | 2 +- .../prompt_image_generation_client/tool.py | 9 +- griptape/tools/rag_client/__init__.py | 0 griptape/tools/rag_client/manifest.yml | 5 + griptape/tools/rag_client/requirements.txt | 0 griptape/tools/rag_client/tool.py | 38 ++ griptape/tools/task_memory_client/tool.py | 4 +- griptape/tools/vector_store_client/tool.py | 32 +- griptape/tools/web_search/tool.py | 40 +- griptape/utils/__init__.py | 6 +- griptape/utils/chat.py | 9 +- griptape/utils/conversation.py | 4 +- griptape/utils/dict_utils.py | 11 +- griptape/utils/file_utils.py | 7 +- griptape/utils/futures.py | 6 + griptape/utils/import_utils.py | 4 +- griptape/utils/load_artifact_from_memory.py | 4 +- griptape/utils/prompt_stack.py | 48 -- griptape/utils/reference_utils.py | 12 + griptape/utils/structure_visualizer.py | 10 +- mkdocs.yml | 5 +- poetry.lock | 513 +++++++++++++++--- pyproject.toml | 32 +- ...st_text_query_task.py => test_rag_task.py} | 16 +- tests/integration/tasks/test_toolkit_task.py | 6 +- tests/mocks/mock_failing_prompt_driver.py | 26 +- tests/mocks/mock_prompt_driver.py | 28 +- tests/mocks/mock_rag_module.py | 4 + tests/mocks/mock_serializable.py | 5 + tests/mocks/mock_value_prompt_driver.py | 21 - tests/unit/artifacts/test_boolean_artifact.py | 35 ++ tests/unit/artifacts/test_text_artifact.py | 8 + .../test_amazon_bedrock_structure_config.py | 59 ++ .../config/test_google_structure_config.py | 2 +- .../test_base_event_listener_driver.py | 12 + .../test_amazon_s3_file_manager_driver.py | 4 +- .../test_local_file_manager_driver.py | 4 +- ...est_dynamodb_conversation_memory_driver.py | 57 +- .../test_local_conversation_memory_driver.py | 8 +- .../test_redis_conversation_memory_driver.py | 4 +- .../test_amazon_bedrock_prompt_driver.py | 61 ++- ...mazon_sagemaker_jumpstart_prompt_driver.py | 14 +- .../prompt/test_anthropic_prompt_driver.py | 98 +++- .../test_azure_openai_chat_prompt_driver.py | 45 +- .../drivers/prompt/test_base_prompt_driver.py | 11 +- .../prompt/test_cohere_prompt_driver.py | 72 ++- .../prompt/test_google_prompt_driver.py | 106 ++-- .../test_hugging_face_hub_prompt_driver.py | 27 +- ...est_hugging_face_pipeline_prompt_driver.py | 16 +- .../prompt/test_ollama_prompt_driver.py | 41 +- .../prompt/test_openai_chat_prompt_driver.py | 107 ++-- tests/unit/drivers/rerank/__init__.py | 0 .../rerank/test_cohere_rerank_driver.py | 26 + .../test_azure_mongodb_vector_store_driver.py | 6 +- .../test_base_local_vector_store_driver.py | 87 +++ tests/unit/drivers/vector/test_entry.py | 12 + .../vector/test_local_vector_store_driver.py | 54 +- .../test_mongodb_atlas_vector_store_driver.py | 6 +- ...st_persistent_local_vector_store_driver.py | 29 + .../test_pinecone_vector_storage_driver.py | 4 +- .../vector/test_qdrant_vector_store_driver.py | 172 ++++++ .../vector/test_redis_vector_store_driver.py | 1 - .../test_proxy_web_scraper_driver.py | 34 ++ tests/unit/drivers/web_search/__init__.py | 0 .../test_duck_duck_go_web_search_driver.py | 36 ++ .../test_google_web_search_driver.py | 43 ++ .../engines/query/test_vector_query_engine.py | 58 -- tests/unit/engines/rag/__init__.py | 0 tests/unit/engines/rag/modules/__init__.py | 0 .../rag/modules/generation/__init__.py | 0 ...est_footnote_prompt_response_rag_module.py | 33 ++ ...est_metadata_before_response_rag_module.py | 21 + .../test_prompt_response_rag_module.py | 25 + ...est_rulesets_before_response_rag_module.py | 10 + .../test_text_chunks_response_rag_module.py | 15 + .../engines/rag/modules/query/__init__.py | 0 .../engines/rag/modules/retrieval/__init__.py | 0 .../test_text_chunks_rerank_rag_module.py | 28 + .../test_text_loader_retrieval_rag_module.py | 26 + .../test_vector_store_retrieval_rag_module.py | 62 +++ .../rag/modules/test_base_rag_nodule.py | 27 + tests/unit/engines/rag/test_rag_context.py | 23 + tests/unit/engines/rag/test_rag_engine.py | 50 ++ .../summary/test_prompt_summary_engine.py | 4 +- tests/unit/events/test_base_event.py | 43 +- tests/unit/events/test_finish_prompt_event.py | 5 +- tests/unit/events/test_start_prompt_event.py | 18 +- .../structure/test_conversation_memory.py | 113 ++-- .../test_summary_conversation_memory.py | 28 +- tests/unit/memory/tool/test_task_memory.py | 2 +- tests/unit/mixins/test_seriliazable_mixin.py | 17 +- tests/unit/structures/test_agent.py | 31 +- tests/unit/structures/test_pipeline.py | 64 ++- tests/unit/structures/test_workflow.py | 56 +- tests/unit/tasks/test_prompt_task.py | 90 +++ tests/unit/tasks/test_rag_task.py | 35 ++ tests/unit/tasks/test_text_query_task.py | 48 -- tests/unit/tasks/test_toolkit_task.py | 24 +- .../unit/tokenizers/test_google_tokenizer.py | 5 +- tests/unit/tools/test_base_tool.py | 4 - tests/unit/tools/test_rag_client.py | 13 + tests/unit/tools/test_vector_store_client.py | 40 +- tests/unit/tools/test_web_search.py | 36 +- tests/unit/utils/test_base_tokenizer.py | 13 + tests/unit/utils/test_dict_utils.py | 21 +- tests/unit/utils/test_futures.py | 9 + tests/unit/utils/test_message_stack.py | 55 ++ tests/unit/utils/test_prompt_stack.py | 41 -- tests/unit/utils/test_structure_visualizer.py | 6 +- tests/utils/code_blocks.py | 3 +- tests/utils/defaults.py | 23 +- tests/utils/test_reference_utils.py | 22 + 285 files changed, 5859 insertions(+), 1923 deletions(-) create mode 100644 .github/pull_request_template.md create mode 100644 _typos.toml create mode 100644 docs/griptape-framework/drivers/web-search-drivers.md create mode 100644 docs/griptape-framework/engines/image-query-engines.md delete mode 100644 docs/griptape-framework/engines/query-engines.md create mode 100644 docs/griptape-framework/engines/rag-engines.md create mode 100644 docs/griptape-tools/official-tools/rag-client.md create mode 100644 griptape/artifacts/boolean_artifact.py create mode 100644 griptape/common/__init__.py rename griptape/{engines/query => common/prompt_stack}/__init__.py (100%) rename {tests/unit/engines/query => griptape/common/prompt_stack/contents}/__init__.py (100%) create mode 100644 griptape/common/prompt_stack/contents/base_delta_message_content.py create mode 100644 griptape/common/prompt_stack/contents/base_message_content.py create mode 100644 griptape/common/prompt_stack/contents/image_message_content.py create mode 100644 griptape/common/prompt_stack/contents/text_delta_message_content.py create mode 100644 griptape/common/prompt_stack/contents/text_message_content.py create mode 100644 griptape/common/prompt_stack/messages/__init__.py create mode 100644 griptape/common/prompt_stack/messages/base_message.py create mode 100644 griptape/common/prompt_stack/messages/delta_message.py create mode 100644 griptape/common/prompt_stack/messages/message.py create mode 100644 griptape/common/prompt_stack/prompt_stack.py create mode 100644 griptape/common/reference.py create mode 100644 griptape/drivers/rerank/__init__.py create mode 100644 griptape/drivers/rerank/base_rerank_driver.py create mode 100644 griptape/drivers/rerank/cohere_rerank_driver.py create mode 100644 griptape/drivers/vector/qdrant_vector_store_driver.py create mode 100644 griptape/drivers/web_scraper/proxy_web_scraper_driver.py create mode 100644 griptape/drivers/web_search/__init__.py create mode 100644 griptape/drivers/web_search/base_web_search_driver.py create mode 100644 griptape/drivers/web_search/duck_duck_go_web_search_driver.py create mode 100644 griptape/drivers/web_search/google_web_search_driver.py delete mode 100644 griptape/engines/query/base_query_engine.py delete mode 100644 griptape/engines/query/vector_query_engine.py create mode 100644 griptape/engines/rag/__init__.py create mode 100644 griptape/engines/rag/modules/__init__.py create mode 100644 griptape/engines/rag/modules/base_rag_module.py create mode 100644 griptape/engines/rag/modules/query/__init__.py create mode 100644 griptape/engines/rag/modules/query/base_query_rag_module.py create mode 100644 griptape/engines/rag/modules/response/__init__.py create mode 100644 griptape/engines/rag/modules/response/base_after_response_rag_module.py create mode 100644 griptape/engines/rag/modules/response/base_before_response_rag_module.py create mode 100644 griptape/engines/rag/modules/response/base_response_rag_module.py create mode 100644 griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py create mode 100644 griptape/engines/rag/modules/response/metadata_before_response_rag_module.py create mode 100644 griptape/engines/rag/modules/response/prompt_response_rag_module.py create mode 100644 griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py create mode 100644 griptape/engines/rag/modules/response/text_chunks_response_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/__init__.py create mode 100644 griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py create mode 100644 griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py create mode 100644 griptape/engines/rag/rag_context.py create mode 100644 griptape/engines/rag/rag_engine.py create mode 100644 griptape/engines/rag/stages/__init__.py create mode 100644 griptape/engines/rag/stages/base_rag_stage.py create mode 100644 griptape/engines/rag/stages/query_rag_stage.py create mode 100644 griptape/engines/rag/stages/response_rag_stage.py create mode 100644 griptape/engines/rag/stages/retrieval_rag_stage.py create mode 100644 griptape/tasks/rag_task.py delete mode 100644 griptape/tasks/text_query_task.py create mode 100644 griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 create mode 100644 griptape/templates/engines/rag/modules/response/metadata/system.j2 create mode 100644 griptape/templates/engines/rag/modules/response/prompt/system.j2 create mode 100644 griptape/tools/rag_client/__init__.py create mode 100644 griptape/tools/rag_client/manifest.yml create mode 100644 griptape/tools/rag_client/requirements.txt create mode 100644 griptape/tools/rag_client/tool.py delete mode 100644 griptape/utils/prompt_stack.py create mode 100644 griptape/utils/reference_utils.py rename tests/integration/tasks/{test_text_query_task.py => test_rag_task.py} (65%) create mode 100644 tests/mocks/mock_rag_module.py delete mode 100644 tests/mocks/mock_value_prompt_driver.py create mode 100644 tests/unit/artifacts/test_boolean_artifact.py create mode 100644 tests/unit/drivers/rerank/__init__.py create mode 100644 tests/unit/drivers/rerank/test_cohere_rerank_driver.py create mode 100644 tests/unit/drivers/vector/test_base_local_vector_store_driver.py create mode 100644 tests/unit/drivers/vector/test_entry.py create mode 100644 tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py create mode 100644 tests/unit/drivers/vector/test_qdrant_vector_store_driver.py create mode 100644 tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py create mode 100644 tests/unit/drivers/web_search/__init__.py create mode 100644 tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py create mode 100644 tests/unit/drivers/web_search/test_google_web_search_driver.py delete mode 100644 tests/unit/engines/query/test_vector_query_engine.py create mode 100644 tests/unit/engines/rag/__init__.py create mode 100644 tests/unit/engines/rag/modules/__init__.py create mode 100644 tests/unit/engines/rag/modules/generation/__init__.py create mode 100644 tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py create mode 100644 tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py create mode 100644 tests/unit/engines/rag/modules/query/__init__.py create mode 100644 tests/unit/engines/rag/modules/retrieval/__init__.py create mode 100644 tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py create mode 100644 tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py create mode 100644 tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py create mode 100644 tests/unit/engines/rag/modules/test_base_rag_nodule.py create mode 100644 tests/unit/engines/rag/test_rag_context.py create mode 100644 tests/unit/engines/rag/test_rag_engine.py create mode 100644 tests/unit/tasks/test_rag_task.py delete mode 100644 tests/unit/tasks/test_text_query_task.py create mode 100644 tests/unit/tools/test_rag_client.py create mode 100644 tests/unit/utils/test_base_tokenizer.py create mode 100644 tests/unit/utils/test_message_stack.py delete mode 100644 tests/unit/utils/test_prompt_stack.py create mode 100644 tests/utils/test_reference_utils.py diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..71a920fcf --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,5 @@ +- [ ] I have read and agree to the contributing guidelines for [submitting new pull requests](https://github.com/griptape-ai/griptape?tab=readme-ov-file#submitting-pull-requests). + +## Describe your changes + +## Issue ticket number and link diff --git a/.github/workflows/code-checks.yml b/.github/workflows/code-checks.yml index 03b1f0a17..51ffc543f 100644 --- a/.github/workflows/code-checks.yml +++ b/.github/workflows/code-checks.yml @@ -70,3 +70,16 @@ jobs: verbose: true env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + spell-check: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: [ "3.12" ] + steps: + - name: Checkout actions + uses: actions/checkout@v3 + - name: Init environment + uses: ./.github/actions/init-environment + - name: Run linter + run: make check/spell diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index f752aa90d..cd21ad1ac 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -119,6 +119,9 @@ jobs: PUSHER_KEY: ${{ secrets.INTEG_PUSHER_KEY }} PUSHER_SECRET: ${{ secrets.INTEG_PUSHER_SECRET }} PUSHER_CLUSTER: ${{ secrets.INTEG_PUSHER_CLUSTER }} + ZENROWS_API_KEY: ${{ secrets.INTEG_ZENROWS_API_KEY }} + QDRANT_CLUSTER_ENDPOINT: ${{ secrets.INTEG_QDRANT_CLUSTER_ENDPOINT }} + QDRANT_CLUSTER_API_KEY: ${{ secrets.INTEG_QDRANT_CLUSTER_API_KEY }} services: postgres: image: ankane/pgvector:v0.5.0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a54182464..33a90d824 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -25,3 +25,10 @@ repos: entry: make check/types language: system types: [python] +- repo: local + hooks: + - id: typos + name: Typos + entry: make check/spell + language: system + types: [python] diff --git a/CHANGELOG.md b/CHANGELOG.md index e1db28e87..9e34ac3a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,85 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.28.0] - 2024-07-09 +### Added +- `RagEngine` is an abstraction for implementing modular RAG pipelines. + - `RagContext` is a container object for passing around RAG context. + - RAG stages: + - `QueryRagStage` for parsing and expanding queries. + - `RetrievalRagStage` for retrieving content. + - `ResponseRagStage` for augmenting and generating outputs. + - RAG modules: + - Retrieval: + - `VectorStoreRetrievalRagModule` for retrieving text chunks from vector stores. + - `TextLoaderRetrievalRagModule` for retrieving data with text loaders in real time. + - `TextChunksRerankRagModule` for re-ranking retrieved results. + - Response: + - `MetadataBeforeResponseRagModule` for appending metadata. + - `RulesetsBeforeResponseRagModule` for appending rulesets. + - `PromptResponseRagModule` for generating responses based on retrieved text chunks. + - `TextChunksResponseRagModule` for responding with retrieved text chunks. + - `FootnotePromptResponseRagModule` for responding with automatic footnotes from text chunk references. +- `RagClient` tool for exposing `RagEngines` to LLM agents. +- `RagTask` task for including `RagEngines` in any structure. +- Rerank drivers: + - `CohereRerankDriver` for using the Cohere rerank API. +- `utils.execute_futures_list()` for executing a list of futures. +- `LocalVectorStoreDriver.persist_file` for persisting vectors and chunks in a text file. +- `Entry.to_artifact()` for easy vector store entry conversions into Griptape artifacts. +- `BaseVectorStoreDriver.does_entry_exist()` to check if an entry exists in the vector store. +- `GoogleWebSearchDriver` to web search with the Google Customsearch API. +- `DuckDuckGoWebSearchDriver` to web search with the DuckDuckGo search SDK. +- `ProxyWebScraperDriver` to web scrape using proxies. +- Parameter `session` on `AmazonBedrockStructureConfig`. +- Parameter `meta` on `TextArtifact`. +- `VectorStoreClient` improvements: + - `VectorStoreClient.query_params` dict for custom query params. + - `VectorStoreClient.process_query_output_fn` for custom query output processing logic. +- Parameter `fail_fast` to `Structure`. +- `BooleanArtifact` for handling boolean values. +- `typos` to dev dependencies to catch typos in code/docs. +- `Message` for storing messages in a `PromptStack`. Messages consist of a role, content, and usage. +- `DeltaMessage` for storing partial messages in a `PromptStack`. Multiple `DeltaMessage` can be combined to form a `Message`. +- `TextMessageContent` for storing textual content in a `Message`. +- `ImageMessageContent` for storing image content in a `Message`. +- Support for adding `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s to `PromptStack`. +- Support for image inputs to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AmazonBedrockPromptDriver`, `AnthropicPromptDriver`, and `GooglePromptDriver`. +- Input/output token usage metrics to all Prompt Drivers. +- `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. +- Support for storing Artifacts as inputs/outputs in Conversation Memory Runs. +- `Agent.input` for passing Artifacts as input. +- Support for `PromptTask`s to take `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s as input. +- Parameters `sort_key` and `sort_key_value` on `AmazonDynamoDbConversationMemoryDriver` for tables with sort keys. +- `Reference` for supporting artifact citations in loaders and RAG engine modules. + +### Changed +- **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. +- **BREAKING**: Renamed `PromptStack.inputs` to `PromptStack.messages`. +- **BREAKING**: Moved `PromptStack.USER_ROLE`, `PromptStack.ASSISTANT_ROLE`, and `PromptStack.SYSTEM_ROLE` to `Message`. +- **BREAKING**: Updated return type of `PromptDriver.try_run` from `TextArtifact` to `Message`. +- **BREAKING**: Updated return type of `PromptDriver.try_stream` from `Iterator[TextArtifact]` to `Iterator[DeltaMessage]`. +- **BREAKING**: Removed `BasePromptEvent.token_count` in favor of `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. +- **BREAKING**: Removed `StartPromptEvent.prompt`. Use `StartPromptEvent.prompt_stack` instead. +- **BREAKING**: Removed `Agent.input_template` in favor of `Agent.input`. +- **BREAKING**: `BasePromptDriver.run` now returns a `Message` instead of a `TextArtifact`. For compatibility, `Message.value` contains the Message's Artifact value +- **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. +- **BREAKING**: Removed `VectorQueryEngine` in favor of `RagEngine`. +- **BREAKING**: Removed `TextQueryTask` in favor of `RagTask`. +- **BREAKING**: `TextArtifactStorage` now requires `vector_store_driver` and `rag_engine` in place of `vector_query_engine`. +- **BREAKING**: Moved `load_artifacts()` from `BaseQueryEngine` to `BaseVectorStoreDriver`. +- **BREAKING**: Merged `BaseVectorStoreDriver.QueryResult` into `BaseVectorStoreDriver.Entry`. +- **BREAKING**: Replaced `query_engine` with `vector_store_driver` in `VectorStoreClient`. +- **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. +- **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. +- **BREAKING**: All `futures_executor` fields renamed to `futures_executor_fn` and now accept callables instead of futures; wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. +- `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. +- Default Prompt Driver model in `GoogleStructureConfig` to `gemini-1.5-pro`. + +### Fixed +- `CoherePromptDriver` to properly handle empty history. +- `StructureVisualizer.to_url()` by wrapping task IDs in single quotes. + ## [0.27.2] - 2024-06-27 ### Fixed @@ -86,6 +165,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Streaming not working when using deprecated `Structure.stream` field. - Raw Tool output being lost when being executed by ActionsSubtask. - Re-order Workflow tasks on every task execution wave. +- `Workflow.insert_task()` enumerates by parent id equality, opposed to object equality. - Web Loader to catch Exceptions and properly return an ErrorArtifact. - Conversation Memory entry only added if `output_task.output` is not `None` on all `Structures` - `TextArtifacts` contained in `ListArtifact` returned by `WebSearch.search` to properly formatted stringified JSON. @@ -105,6 +185,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `PusherEventListenerDriver` to enable sending of framework events over a Pusher WebSocket. ### Changed +- **BREAKING**: Updated OpenAI-based image query drivers to remove Vision from the name. +- **BREAKING**: `off_prompt` now defaults to `False` on all Tools, making Task Memory something that must be explicitly opted into. - **BREAKING**: Removed `StructureConfig.global_drivers`. Pass Drivers directly to the Structure Config instead. - **BREAKING**: Removed `StructureConfig.task_memory` in favor of configuring directly on the Structure. - **BREAKING**: Updated OpenAI-based image query drivers to remove Vision from the name. @@ -120,6 +202,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Extra fields being excluded when using `SerializableMixin.from_dict`. +- Validation of `max_tokens` < 0 on `BaseChunker` ## [0.25.1] - 2024-05-15 @@ -211,6 +294,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `MarkdownifyWebScraperDriver` for scraping text from web pages using playwright and converting to markdown using markdownify. - `VoyageAiEmbeddingDriver` for use with VoyageAi's embedding models. - `AnthropicStructureConfig` for providing Structures with Anthropic Prompt and VoyageAi Embedding Driver configuration. +- `QdrantVectorStoreDriver` to integrate with Qdrant vector databases. ### Fixed - Improved system prompt in `ToolTask` to support more use cases. @@ -316,7 +400,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ImageLoader` for loading images files into `ImageArtifact`s. - Support for all Tokenizers in `OpenAiChatPromptDriver`, enabling OpenAI drop-in clients such as Together AI. -- `AmazonSageMakerEmbeddingDriver` for using Amazon SageMaker to generate embeddings. Thanks @KaushikIyer16! +- `AmazonSageMakerJumpstartEmbeddingDriver` for using Amazon SageMaker to generate embeddings. Thanks @KaushikIyer16! - Claude 2.1 support in `AnthropicPromptDriver` and `AmazonBedrockPromptDriver` via `BedrockClaudePromptModelDriver`. - `CodeExecutionTask` for executing code as a Task without the need for an LLM. - `BedrockLlamaPromptModelDriver` for using Llama models on Amazon Bedrock. diff --git a/Makefile b/Makefile index b4f3d0068..13410094c 100644 --- a/Makefile +++ b/Makefile @@ -16,8 +16,8 @@ publish: ## Push git tag and publish version to PyPI. install: ## Install all dependencies. @poetry install --with dev --with test --with docs --all-extras -.PHONY: test -test: test/unit test/integration ## Run all tests. +.PHONY: test ## Run all tests. +test: test/unit test/integration .PHONY: test/unit test/unit: ## Run unit tests. @@ -40,7 +40,7 @@ format: ## Format project. @poetry run ruff format . .PHONY: check -check: check/format check/lint check/types ## Run all checks. +check: check/format check/lint check/types check/spell ## Run all checks. .PHONY: check/format check/format: @@ -53,6 +53,14 @@ check/lint: .PHONY: check/types check/types: @poetry run pyright griptape/ + +.PHONY: check/spell +check/spell: + @poetry run typos + +.PHONY: docs +docs: ## Build documentation. + @poetry run mkdocs build .DEFAULT_GOAL := help .PHONY: help diff --git a/README.md b/README.md index b5e4f7bcb..42df8fbd6 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![Checked with pyright](https://microsoft.github.io/pyright/img/pyright_badge.svg)](https://microsoft.github.io/pyright/) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![codecov](https://codecov.io/github/griptape-ai/griptape/graph/badge.svg?token=HUBqUpl3NB)](https://codecov.io/github/griptape-ai/griptape) -[![Griptape Discord](https://dcbadge.vercel.app/api/server/gnWRz88eym?compact=true&style=flat)](https://discord.gg/gnWRz88eym) +[![Griptape Discord](https://dcbadge.vercel.app/api/server/gnWRz88eym?compact=true&style=flat)](https://discord.gg/griptape) Griptape is a modular Python framework for building AI-powered applications that securely connect to your enterprise data and APIs. It offers developers the ability to maintain control and flexibility at every step. @@ -50,7 +50,7 @@ Drivers facilitate interactions with external resources and services: Engines wrap Drivers and provide use-case-specific functionality: -- 📊 **Query Engines** execute Retrieval Augmented Generation (RAG) queries. +- 📊 **RAG Engine** is an abstraction for implementing modular Retrieval Augmented Generation (RAG) pipelines. - 🛠️ **Extraction Engines** extract JSON or CSV data from unstructured text. - 📝 **Summary Engines** generate summaries from textual content. - 🖼️ **Image Generation Engines** generate images from textual descriptions. @@ -92,7 +92,7 @@ from griptape.structures import Agent from griptape.tools import WebScraper, FileManager, TaskMemoryClient agent = Agent( - input_template="Load {{ args[0] }}, summarize it, and store it in a file called {{ args[1] }}.", + input="Load {{ args[0] }}, summarize it, and store it in a file called {{ args[1] }}.", tools=[ WebScraper(off_prompt=True), TaskMemoryClient(off_prompt=True), @@ -162,12 +162,6 @@ Thank you for considering contributing to Griptape! Before you start, please rea If you have identified a bug, want to propose a new feature, or have a question, please submit an issue through our public [issue tracker](https://github.com/griptape-ai/griptape/issues). Before submitting a new issue, please check the existing issues to ensure it hasn't been reported or discussed before. -### New Griptape Tools - -Griptape's extensibility allows anyone to develop and distribute tools independently. With rare exceptions for Tools providing broadly applicable functionality, new Griptape Tools should be managed as their own projects and not submitted to the core framework. Pull requests for new tools (unless addressing an [existing issue](https://github.com/griptape-ai/griptape/issues)) will be closed. - -The [Griptape Tool Template](https://github.com/griptape-ai/tool-template) provides the recommended structure, step-by-step instructions, basic automation, and usage examples for new Tools. In the Template, select **Use this template** then **Create a new repository** to begin a new Tool project. - ### Submitting Pull Requests We welcome and encourage pull requests. To streamline the process, please follow these guidelines: @@ -178,13 +172,27 @@ We welcome and encourage pull requests. To streamline the process, please follow 3. **Unit Tests:** Ensure that your pull request passes all existing unit tests. Additionally, if you are introducing new code, please include new unit tests to validate its functionality. +Run `make test/unit` to execute the test suite locally. + 4. **Documentation:** Every pull request must include updates to documentation or explicitly explain why a documentation update is not required. Documentation is crucial for maintaining a comprehensive and user-friendly project. -5. **Code Style:** Griptape uses [Ruff](https://github.com/astral-sh/ruff) to enforce style guidelines. You can ensure that your code is formatted accordingly and will pass formatting checks using `pre-commit`. See [Tools](#tools) for information on how to configure this and other dev tools. +Run `make docs` to build the documentation locally. + +5. **Code Checks:** Griptape a variety of tools to enforce code quality and style. Your code must pass all checks before it can be merged. + +Run `make check` to run all code checks locally. + +6. **Changelog:** If your pull request introduces a notable change, please update the [changelog](https://github.com/griptape-ai/griptape/blob/dev/CHANGELOG.md). + +### New Griptape Tools + +Griptape's extensibility allows anyone to develop and distribute tools independently. With rare exceptions for Tools providing broadly applicable functionality, new Griptape Tools should be managed as their own projects and not submitted to the core framework. Pull requests for new tools (unless addressing an [existing issue](https://github.com/griptape-ai/griptape/issues)) will be closed. + +The [Griptape Tool Template](https://github.com/griptape-ai/tool-template) provides the recommended structure, step-by-step instructions, basic automation, and usage examples for new Tools. In the Template, select **Use this template** then **Create a new repository** to begin a new Tool project. -### Tools +### Dev and Test Dependencies -Install dev dependencies via Make: +Install all dependencies via Make: ```shell make install diff --git a/_typos.toml b/_typos.toml new file mode 100644 index 000000000..1819b51ef --- /dev/null +++ b/_typos.toml @@ -0,0 +1,8 @@ +[default.extend-words] +# Don't correct the state ND +ND = "ND" +# Don't correct pirates using acronyms +mornin = "mornin" + +[files] +extend-exclude = ["docs/assets", "tests/resources/"] diff --git a/docs/examples/load-query-and-chat-marqo.md b/docs/examples/load-query-and-chat-marqo.md index 718b42729..fb5906e9e 100644 --- a/docs/examples/load-query-and-chat-marqo.md +++ b/docs/examples/load-query-and-chat-marqo.md @@ -2,11 +2,10 @@ import os from griptape import utils from griptape.drivers import MarqoVectorStoreDriver -from griptape.engines import VectorQueryEngine from griptape.loaders import WebLoader from griptape.structures import Agent from griptape.tools import VectorStoreClient -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.drivers import OpenAiEmbeddingDriver # Define the namespace namespace = "griptape-ai" @@ -18,14 +17,12 @@ vector_store = MarqoVectorStoreDriver( index=os.environ["MARQO_INDEX_NAME"], embedding_driver=OpenAiEmbeddingDriver() ) -# Initialize the query engine -query_engine = VectorQueryEngine(vector_store_driver=vector_store, prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo")) # Initialize the knowledge base tool vector_store_tool = VectorStoreClient( description="Contains information about the Griptape Framework from www.griptape.ai", - query_engine=query_engine, namespace=namespace, + vector_store_driver=vector_store ) # Load artifacts from the web diff --git a/docs/examples/multi-agent-workflow.md b/docs/examples/multi-agent-workflow.md index d0fa65232..4a26625b3 100644 --- a/docs/examples/multi-agent-workflow.md +++ b/docs/examples/multi-agent-workflow.md @@ -7,7 +7,7 @@ Additionally, this architecture opens us up to using services such as [Griptape ```python import os -from griptape.drivers import WebhookEventListenerDriver, LocalStructureRunDriver +from griptape.drivers import WebhookEventListenerDriver, LocalStructureRunDriver, GoogleWebSearchDriver from griptape.events import EventListener, FinishStructureRunEvent from griptape.rules import Rule, Ruleset from griptape.structures import Agent, Workflow @@ -38,8 +38,10 @@ def build_researcher(): id="researcher", tools=[ WebSearch( - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + ), ), WebScraper( off_prompt=True, diff --git a/docs/examples/multiple-agent-shared-memory.md b/docs/examples/multiple-agent-shared-memory.md index cc5498d7e..109394d49 100644 --- a/docs/examples/multiple-agent-shared-memory.md +++ b/docs/examples/multiple-agent-shared-memory.md @@ -8,13 +8,9 @@ The `MongoDbAtlasVectorStoreDriver` assumes that you have a vector index configu ```python import os -from griptape.tools import WebScraper, VectorStoreClient, TaskMemoryClient +from griptape.tools import WebScraper, TaskMemoryClient from griptape.structures import Agent from griptape.drivers import AzureOpenAiEmbeddingDriver, AzureMongoDbVectorStoreDriver -from griptape.engines import VectorQueryEngine, PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine -from griptape.memory import TaskMemory -from griptape.artifacts import TextArtifact -from griptape.memory.task.storage import TextArtifactStorage from griptape.config import AzureOpenAiStructureConfig diff --git a/docs/examples/query-webpage.md b/docs/examples/query-webpage.md index d11c5d9c4..07801b32c 100644 --- a/docs/examples/query-webpage.md +++ b/docs/examples/query-webpage.md @@ -22,7 +22,7 @@ results = vector_store.query( namespace="griptape" ) -values = [BaseArtifact.from_json(r.meta["artifact"]).value for r in results] +values = [r.to_artifact().value for r in results] print("\n\n".join(values)) ``` \ No newline at end of file diff --git a/docs/examples/talk-to-a-pdf.md b/docs/examples/talk-to-a-pdf.md index 51f71b4f6..a3f47f0c6 100644 --- a/docs/examples/talk-to-a-pdf.md +++ b/docs/examples/talk-to-a-pdf.md @@ -1,48 +1,56 @@ This example demonstrates how to vectorize a PDF of the [Attention Is All You Need](https://arxiv.org/pdf/1706.03762.pdf) paper and setup a Griptape agent with rules and the [VectorStoreClient](../reference/griptape/tools/vector_store_client/tool.md) tool to use it during conversations. ```python -import os -import io import requests -from griptape.engines import VectorQueryEngine +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.loaders import PdfLoader from griptape.structures import Agent -from griptape.tools import VectorStoreClient +from griptape.tools import RagClient from griptape.utils import Chat -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver - namespace = "attention" - response = requests.get("https://arxiv.org/pdf/1706.03762.pdf") - -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver( - model="gpt-3.5-turbo", +vector_store = LocalVectorStoreDriver( + embedding_driver=OpenAiEmbeddingDriver() +) +engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store, + query_params={ + "namespace": namespace, + "top_n": 20 + + } + ) + ] ), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=OpenAiEmbeddingDriver( - api_key=os.environ["OPENAI_API_KEY"] + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) ) +vector_store_tool = RagClient( + description="Contains information about the Attention Is All You Need paper. " + "Use it to answer any related questions.", + rag_engine=engine +) -engine.vector_store_driver.upsert_text_artifacts( +vector_store.upsert_text_artifacts( { namespace: PdfLoader().load(response.content) } ) -vector_store_tool = VectorStoreClient( - description="Contains information about the Attention Is All You Need paper. " - "Use it to answer any related questions.", - query_engine=engine, - namespace=namespace, -) - agent = Agent( tools=[vector_store_tool] ) Chat(agent).start() + ``` diff --git a/docs/examples/talk-to-a-webpage.md b/docs/examples/talk-to-a-webpage.md index 2f2cbf209..d1d0da5fa 100644 --- a/docs/examples/talk-to-a-webpage.md +++ b/docs/examples/talk-to-a-webpage.md @@ -1,25 +1,36 @@ -This example demonstrates how to vectorize a webpage and setup a Griptape agent with rules and the [VectorStoreClient](../reference/griptape/tools/vector_store_client/tool.md) tool to use it during conversations. +This example demonstrates how to vectorize a webpage and setup a Griptape agent with rules and the [RagClient](../reference/griptape/tools/rag_client/tool.md) tool to use it during conversations. ```python -import os -from griptape.engines import VectorQueryEngine +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.loaders import WebLoader from griptape.rules import Ruleset, Rule from griptape.structures import Agent -from griptape.tools import VectorStoreClient +from griptape.tools import RagClient from griptape.utils import Chat -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver - namespace = "physics-wiki" -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver( - model="gpt-3.5-turbo", +vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + +engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, + query_params={ + "namespace": namespace, + "top_n": 20 + + } + ) + ] ), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=OpenAiEmbeddingDriver( - api_key=os.environ["OPENAI_API_KEY"] + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) ) @@ -28,16 +39,14 @@ artifacts = WebLoader().load( "https://en.wikipedia.org/wiki/Physics" ) -engine.vector_store_driver.upsert_text_artifacts( +vector_store_driver.upsert_text_artifacts( {namespace: artifacts} ) - -vector_store_tool = VectorStoreClient( +vector_store_tool = RagClient( description="Contains information about physics. " "Use it to answer any physics-related questions.", - query_engine=engine, - namespace=namespace, + rag_engine=engine ) agent = Agent( diff --git a/docs/griptape-framework/data/artifacts.md b/docs/griptape-framework/data/artifacts.md index 5b69b120a..6fe77574b 100644 --- a/docs/griptape-framework/data/artifacts.md +++ b/docs/griptape-framework/data/artifacts.md @@ -1,11 +1,11 @@ ## Overview -**Artifacts** are used for passing different types of data between Griptape components. All tools return artifacts that are later consumed by tasks and task memory. +**[Artifacts](../../reference/griptape/artifacts/base_artifact.md)** are used for passing different types of data between Griptape components. All tools return artifacts that are later consumed by tasks and task memory. Artifacts make sure framework components enforce contracts when passing and consuming data. ## TextArtifact -Used for passing text data of arbitrary size around the framework. It can be used to count tokens with [token_count()](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.token_count) with a tokenizer. +A [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) for passing text data of arbitrary size around the framework. It can be used to count tokens with [token_count()](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.token_count) with a tokenizer. It can also be used to generate a text embedding with [generate_embedding()](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.generate_embedding) and access it with [embedding](../../reference/griptape/artifacts/text_artifact.md#griptape.artifacts.text_artifact.TextArtifact.embedding). @@ -13,20 +13,20 @@ and access it with [embedding](../../reference/griptape/artifacts/text_artifact. ## CsvRowArtifact -Used for passing structured row data around the framework. It inherits from [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) and overrides the +A [CsvRowArtifact](../../reference/griptape/artifacts/csv_row_artifact.md) for passing structured row data around the framework. It inherits from [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) and overrides the [to_text()](../../reference/griptape/artifacts/csv_row_artifact.md#griptape.artifacts.csv_row_artifact.CsvRowArtifact.to_text) method, which always returns a valid CSV row. ## InfoArtifact -Used for passing short notifications back to the LLM without task memory storing them. +An [InfoArtifact](../../reference/griptape/artifacts/info_artifact.md) for passing short notifications back to the LLM without task memory storing them. ## ErrorArtifact -Used for passing errors back to the LLM without task memory storing them. +An [ErrorArtifact](../../reference/griptape/artifacts/error_artifact.md) is used for passing errors back to the LLM without task memory storing them. ## BlobArtifact -Used for passing binary large objects (blobs) back to the LLM. +A [BlobArtifact](../../reference/griptape/artifacts/blob_artifact.md) for passing binary large objects (blobs) back to the LLM. Treat it as a way to return unstructured data, such as images, videos, audio, and other files back from tools. Each blob has a [name](../../reference/griptape/artifacts/base_artifact.md#griptape.artifacts.base_artifact.BaseArtifact.name) and [dir](../../reference/griptape/artifacts/blob_artifact.md#griptape.artifacts.blob_artifact.BlobArtifact.dir_name) to uniquely identify stored objects. @@ -40,3 +40,10 @@ An [ImageArtifact](../../reference/griptape/artifacts/image_artifact.md) is used ## AudioArtifact An [AudioArtifact](../../reference/griptape/artifacts/audio_artifact.md) allows the Framework to interact with audio content. An Audio Artifact includes binary audio content as well as metadata like format, duration, and prompt and model information for audio returned generative models. It inherits from [BlobArtifact](#blobartifact). + +## BooleanArtifact + +A [BooleanArtifact](../../reference/griptape/artifacts/boolean_artifact.md) is used for passing boolean values around the framework. + +!!! info + Any object passed on init to `BooleanArtifact` will be coerced into a `bool` type. This might lead to unintended behavior: `BooleanArtifact("False").value is True`. Use [BooleanArtifact.parse_bool](../../reference/griptape/artifacts/boolean_artifact.md#griptape.artifacts.boolean_artifact.BooleanArtifact.parse_bool) to convert case-insensitive string literal values `"True"` and `"False"` into a `BooleanArtifact`: `BooleanArtifact.parse_bool("False").value is False`. diff --git a/docs/griptape-framework/data/index.md b/docs/griptape-framework/data/index.md index 73dfe4c66..3e4359737 100644 --- a/docs/griptape-framework/data/index.md +++ b/docs/griptape-framework/data/index.md @@ -14,7 +14,17 @@ Griptape provides several abstractions for working with data. **Tokenizers** are used to tokenize and detokenize text in order to track LLM token limits. -[Query Engines](../engines/query-engines.md) are used to search text storages. +[Audio Engines](../engines/audio-engines.md) are used for working with audio. + +[Extraction Engines](../engines/extraction-engines.md) are used for extracting structured content. + +[Image Query Engines](../engines/image-query-engines.md) are used for querying images with text. + +[Image Generation Engines](../engines/image-generation-engines.md) are used for generating images. + +[Summary Engines](../engines/summary-engines.md) are used for summarizing text content. + +[RAG Engines](../engines/rag-engines.md) are used for implementing modular RAG pipelines. [Vector Store Drivers](../drivers/vector-store-drivers.md) are used to store and query vector databases. diff --git a/docs/griptape-framework/drivers/audio-transcription-drivers.md b/docs/griptape-framework/drivers/audio-transcription-drivers.md index ddadcb89a..c89ef9699 100644 --- a/docs/griptape-framework/drivers/audio-transcription-drivers.md +++ b/docs/griptape-framework/drivers/audio-transcription-drivers.md @@ -6,6 +6,8 @@ This driver acts as a critical bridge between audio transcription Engines and th This capability is essential for enhancing accessibility, improving content discoverability, and automating tasks that traditionally relied on manual transcription, thereby streamlining operations and enhancing efficiency across various industries. +## Audio Transcription Drivers + ### OpenAI The [OpenAI Audio Transcription Driver](../../reference/griptape/drivers/audio_transcription/openai_audio_transcription_driver.md) utilizes OpenAI's sophisticated `whisper` model to accurately transcribe spoken audio into text. This model supports multiple languages, ensuring precise transcription across a wide range of dialects. diff --git a/docs/griptape-framework/drivers/conversation-memory-drivers.md b/docs/griptape-framework/drivers/conversation-memory-drivers.md index 2ca5f8dd3..88063292f 100644 --- a/docs/griptape-framework/drivers/conversation-memory-drivers.md +++ b/docs/griptape-framework/drivers/conversation-memory-drivers.md @@ -2,6 +2,8 @@ You can persist and load memory by using Conversation Memory Drivers. You can build drivers for your own data stores by extending [BaseConversationMemoryDriver](../../reference/griptape/drivers/memory/conversation/base_conversation_memory_driver.md). +## Conversation Memory Drivers + ### Local The [LocalConversationMemoryDriver](../../reference/griptape/drivers/memory/conversation/local_conversation_memory_driver.md) allows you to persist Conversation Memory in a local JSON file. @@ -45,6 +47,7 @@ agent = Agent(conversation_memory=ConversationMemory(driver=dynamodb_driver)) agent.run("My name is Jeff.") agent.run("What is my name?") ``` +Optional parameters `sort_key` and `sort_key_value` can be supplied for tables with a composite primary key. ### Redis diff --git a/docs/griptape-framework/drivers/image-generation-drivers.md b/docs/griptape-framework/drivers/image-generation-drivers.md index 25572ba9c..95a8bf49b 100644 --- a/docs/griptape-framework/drivers/image-generation-drivers.md +++ b/docs/griptape-framework/drivers/image-generation-drivers.md @@ -23,6 +23,8 @@ agent = Agent(tools=[ agent.run("Generate a watercolor painting of a dog riding a skateboard") ``` +## Image Generation Drivers + ### Amazon Bedrock The [Amazon Bedrock Image Generation Driver](../../reference/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.md) provides multi-model access to image generation models hosted by Amazon Bedrock. This Driver manages API calls to the Bedrock API, while the specific Model Drivers below format the API requests and parse the responses. diff --git a/docs/griptape-framework/drivers/image-query-drivers.md b/docs/griptape-framework/drivers/image-query-drivers.md index 8003924b1..6fde89b80 100644 --- a/docs/griptape-framework/drivers/image-query-drivers.md +++ b/docs/griptape-framework/drivers/image-query-drivers.md @@ -1,11 +1,13 @@ -# Image Query Drivers +## Overview -Image Query Drivers are used by [Image Query Engines](../engines/query-engines.md#image) to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular Image Query Driver. +Image Query Drivers are used by [Image Query Engines](../engines/image-query-engines.md) to execute natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular Image Query Driver. !!! info All Image Query Drivers default to a `max_tokens` of 256. It is recommended that you set this value to correspond to the desired response length. -## Anthropic +## Image Query Drivers + +### Anthropic !!! info To tune `max_tokens`, see [Anthropic's documentation on image tokens](https://docs.anthropic.com/claude/docs/vision#image-costs) for more information on how to relate token count to response length. @@ -59,7 +61,7 @@ result = engine.run("Describe the weather in the image", [image_artifact1, image print(result) ``` -## OpenAI +### OpenAI !!! info While the `max_tokens` field is optional, it is recommended to set this to a value that corresponds to the desired response length. Without an explicit value, the model will default to very short responses. See [OpenAI's documentation](https://help.openai.com/en/articles/4936856-what-are-tokens-and-how-to-count-them) for more information on how to relate token count to response length. @@ -86,7 +88,7 @@ with open("tests/resources/mountain.png", "rb") as f: engine.run("Describe the weather in the image", [image_artifact]) ``` -## Azure OpenAI +### Azure OpenAI !!! info In order to use the `gpt-4-vision-preview` model on Azure OpenAI, the `gpt-4` model must be deployed with the version set to `vision-preview`. More information can be found in the [Azure OpenAI documentation](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/gpt-with-vision). @@ -117,11 +119,11 @@ with open("tests/resources/mountain.png", "rb") as f: engine.run("Describe the weather in the image", [image_artifact]) ``` -## Amazon Bedrock +### Amazon Bedrock The [Amazon Bedrock Image Query Driver](../../reference/griptape/drivers/image_query/amazon_bedrock_image_query_driver.md) provides multi-model access to image query models hosted by Amazon Bedrock. This Driver manages API calls to the Bedrock API, while the specific Model Drivers below format the API requests and parse the responses. -### Claude +#### Claude The [BedrockClaudeImageQueryModelDriver](../../reference/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.md) provides support for Claude models hosted by Bedrock. diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index 0100ccbac..a846cbb5b 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -14,7 +14,7 @@ agent = Agent( config=StructureConfig( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o", temperature=0.3), ), - input_template="You will be provided with a tweet, and your task is to classify its sentiment as positive, neutral, or negative. Tweet: {{ args[0] }}", + input="You will be provided with a tweet, and your task is to classify its sentiment as positive, neutral, or negative. Tweet: {{ args[0] }}", rules=[ Rule( value="Output only the sentiment." @@ -28,23 +28,23 @@ agent.run("I loved the new Batman movie!") Or use them independently: ```python -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.drivers import OpenAiChatPromptDriver stack = PromptStack() -stack.add_system_input( +stack.add_system_message( "You will be provided with Python code, and your task is to calculate its time complexity." ) -stack.add_user_input( -""" -def foo(n, k): - accum = 0 - for i in range(n): - for l in range(k): - accum += i - return accum -""" +stack.add_user_message( + """ + def foo(n, k): + accum = 0 + for i in range(n): + for l in range(k): + accum += i + return accum + """ ) result = OpenAiChatPromptDriver(model="gpt-3.5-turbo-16k", temperature=0).run(stack) @@ -57,7 +57,7 @@ print(result.value) Griptape offers the following Prompt Drivers for interacting with LLMs. !!! warning - When overriding a default Prompt Driver, take care to ensure you've updated the Structure's configured Embedding Driver as well. If Task Memory isn't needed, you can avoid compatability issues by setting `task_memory=None` to disable Task Memory in your Structure. + When overriding a default Prompt Driver, take care to ensure you've updated the Structure's configured Embedding Driver as well. If Task Memory isn't needed, you can avoid compatibility issues by setting `task_memory=None` to disable Task Memory in your Structure. ### OpenAI Chat @@ -80,7 +80,7 @@ agent = Agent( seed=42, ) ), - input_template="You will be provided with a description of a mood, and your task is to generate the CSS code for a color that matches it. Description: {{ args[0] }}", + input="You will be provided with a description of a mood, and your task is to generate the CSS code for a color that matches it. Description: {{ args[0] }}", rules=[ Rule( value='Write your output in json with a single key called "css_code".' @@ -141,7 +141,7 @@ from griptape.config import StructureConfig agent = Agent( config=StructureConfig( prompt_driver=CoherePromptDriver( - model="command", + model="command-r", api_key=os.environ['COHERE_API_KEY'], ) ) diff --git a/docs/griptape-framework/drivers/sql-drivers.md b/docs/griptape-framework/drivers/sql-drivers.md index c4b7dbcca..c0f8e9f99 100644 --- a/docs/griptape-framework/drivers/sql-drivers.md +++ b/docs/griptape-framework/drivers/sql-drivers.md @@ -8,7 +8,9 @@ SQL drivers can be used to make SQL queries and load table schemas. They are use !!! info More database-specific SQL drivers are coming soon. -## SQL +## SQL Drivers + +### SQL This is a basic SQL loader based on [SQLAlchemy 1.x](https://docs.sqlalchemy.org/en/14/). Here is an example of how to use it: @@ -22,7 +24,7 @@ driver = SqlDriver( driver.execute_query("select 'foo', 'bar';") ``` -## Amazon Redshift +### Amazon Redshift !!! info This driver requires the `drivers-sql-redshift` [extra](../index.md#extras). @@ -46,7 +48,7 @@ driver = AmazonRedshiftSqlDriver( driver.execute_query("select * from people;") ``` -## Snowflake +### Snowflake !!! info This driver requires the `drivers-sql-snowflake` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/structure-run-drivers.md b/docs/griptape-framework/drivers/structure-run-drivers.md index 54413c3a2..bba3de524 100644 --- a/docs/griptape-framework/drivers/structure-run-drivers.md +++ b/docs/griptape-framework/drivers/structure-run-drivers.md @@ -2,7 +2,9 @@ Structure Run Drivers can be used to run Griptape Structures in a variety of runtime environments. When combined with the [Structure Run Task](../../griptape-framework/structures/tasks.md#structure-run-task) or [Structure Run Client](../../griptape-tools/official-tools/structure-run-client.md) you can create complex, multi-agent pipelines that span multiple runtime environments. -## Local +## Structure Run Drivers + +### Local The [LocalStructureRunDriver](../../reference/griptape/drivers/structure_run/local_structure_run_driver.md) is used to run Griptape Structures in the same runtime environment as the code that is running the Structure. @@ -53,7 +55,7 @@ joke_coordinator = Pipeline( joke_coordinator.run("Tell me a joke") ``` -## Griptape Cloud +### Griptape Cloud The [GriptapeCloudStructureRunDriver](../../reference/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.md) is used to run Griptape Structures in the Griptape Cloud. diff --git a/docs/griptape-framework/drivers/text-to-speech-drivers.md b/docs/griptape-framework/drivers/text-to-speech-drivers.md index a37d4d33e..5f1823fdc 100644 --- a/docs/griptape-framework/drivers/text-to-speech-drivers.md +++ b/docs/griptape-framework/drivers/text-to-speech-drivers.md @@ -4,6 +4,8 @@ Provide a Driver when building an [Engine](../engines/audio-engines.md), then pass it to a [Tool](../tools/index.md) for use by an [Agent](../structures/agents.md): +## Text to Speech Drivers + ### Eleven Labs The [Eleven Labs Text to Speech Driver](../../reference/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.md) provides support for text-to-speech models hosted by Eleven Labs. This Driver supports configurations specific to Eleven Labs, like voice selection and output format. diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 481a2dd84..da6fdc242 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -16,7 +16,9 @@ Each vector driver takes a [BaseEmbeddingDriver](../../reference/griptape/driver !!! info More vector drivers are coming soon. -## Local +## Vector Store Drivers + +### Local The [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) can be used to load and query data from memory. Here is a complete example of how the driver can be used to load a webpage into the driver and query it later: @@ -41,13 +43,13 @@ results = vector_store_driver.query( namespace="griptape" ) -values = [BaseArtifact.from_json(r.meta["artifact"]).value for r in results] +values = [r.to_artifact().value for r in results] print("\n\n".join(values)) ``` -## Pinecone +### Pinecone !!! info This driver requires the `drivers-vector-pinecone` [extra](../index.md#extras). @@ -103,7 +105,7 @@ result = vector_store_driver.query( ) ``` -## Marqo +### Marqo !!! info This driver requires the `drivers-vector-marqo` [extra](../index.md#extras). @@ -115,9 +117,7 @@ Here is an example of how the driver can be used to load and query information i ```python import os from griptape.drivers import MarqoVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver -from griptape.engines import VectorQueryEngine from griptape.loaders import WebLoader -from griptape.tools import VectorStoreClient # Initialize an embedding driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) @@ -134,30 +134,21 @@ vector_store = MarqoVectorStoreDriver( embedding_driver=embedding_driver, ) -# Initialize the query engine -query_engine = VectorQueryEngine(vector_store_driver=vector_store, prompt_driver=prompt_driver) - -# Initialize the knowledge base tool -VectorStoreClient( - description="Contains information about the Griptape Framework from www.griptape.ai", - query_engine=query_engine, - namespace=namespace, -) - # Load artifacts from the web artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") # Upsert the artifacts into the vector store vector_store.upsert_text_artifacts( { - namespace: artifacts, + "griptape": artifacts, } ) + result = vector_store.query(query="What is griptape?") print(result) ``` -## Mongodb Atlas +### Mongodb Atlas !!! info This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). @@ -225,7 +216,7 @@ The format for creating a vector index should look similar to the following: ``` Replace `path_to_vector` with the expected field name where the vector content will be. -## Azure MongoDB +### Azure MongoDB !!! info This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). @@ -274,7 +265,7 @@ result = vector_store.query(query="What is griptape?") print(result) ``` -## Redis +### Redis !!! info This driver requires the `drivers-vector-redis` [extra](../index.md#extras). @@ -319,7 +310,7 @@ The format for creating a vector index should be similar to the following: FT.CREATE idx:griptape ON hash PREFIX 1 "griptape:" SCHEMA namespace TAG vector VECTOR FLAT 6 TYPE FLOAT32 DIM 1536 DISTANCE_METRIC COSINE ``` -## OpenSearch +### OpenSearch !!! info This driver requires the `drivers-vector-opensearch` [extra](../index.md#extras). @@ -372,7 +363,7 @@ The body mappings for creating a vector index should look similar to the followi } ``` -## PGVector +### PGVector !!! info This driver requires the `drivers-vector-postgresql` [extra](../index.md#extras). @@ -415,3 +406,65 @@ vector_store_driver.upsert_text_artifacts( result = vector_store_driver.query("What is griptape?") print(result) ``` + +### Qdrant + +!!! info + This driver requires the `drivers-vector-qdrant` [extra](../index.md#extras). + +The QdrantVectorStoreDriver supports the [Qdrant vector database](https://qdrant.tech/). + +Here is an example of how the driver can be used to query information in a Qdrant collection: + +```python +import os +from griptape.drivers import QdrantVectorStoreDriver, HuggingFaceHubEmbeddingDriver +from griptape.tokenizers import HuggingFaceTokenizer +from griptape.loaders import WebLoader + +# Set up environment variables +embedding_model_name = "sentence-transformers/all-MiniLM-L6-v2" +host = os.environ["QDRANT_CLUSTER_ENDPOINT"] +huggingface_token = os.environ["HUGGINGFACE_HUB_ACCESS_TOKEN"] + +# Initialize HuggingFace embedding driver +embedding_driver = HuggingFaceHubEmbeddingDriver( + api_token=huggingface_token, + model=embedding_model_name, + tokenizer=HuggingFaceTokenizer(model=embedding_model_name, max_output_tokens=512), +) + +# Initialize Qdrant vector store driver +vector_store_driver = QdrantVectorStoreDriver( + url=host, + collection_name="griptape", + content_payload_key="content", + embedding_driver=embedding_driver, + api_key=os.environ["QDRANT_CLUSTER_API_KEY"], +) + +# Load data from the website +artifacts = WebLoader().load("https://www.griptape.ai") + +# Encode text to get embeddings +embeddings = embedding_driver.embed_text_artifact(artifacts[0]) + +# Recreate Qdrant collection +vector_store_driver.client.recreate_collection( + collection_name=vector_store_driver.collection_name, + vectors_config={ + "size": len(embeddings), + "distance": vector_store_driver.distance + }, +) + +# Upsert vector into Qdrant +vector_store_driver.upsert_vector( + vector=embeddings, + vector_id=str(artifacts[0].id), + content=artifacts[0].value +) + +print("Vectors successfully inserted into Qdrant.") + +``` diff --git a/docs/griptape-framework/drivers/web-scraper-drivers.md b/docs/griptape-framework/drivers/web-scraper-drivers.md index a02365b67..8c05a3df2 100644 --- a/docs/griptape-framework/drivers/web-scraper-drivers.md +++ b/docs/griptape-framework/drivers/web-scraper-drivers.md @@ -4,7 +4,39 @@ Web Scraper Drivers can be used to scrape text from the web. They are used by [W * `scrape_url()` scrapes text from a website and returns a [TextArtifact](../../reference/griptape/artifacts/text_artifact.md). The format of the scrapped text is determined by the Driver. -## Markdownify +## Web Scraper Drivers + +### Proxy + +The [ProxyWebScraperDriver](../../reference/griptape/drivers/web_scraper/proxy_web_scraper_driver.md) uses the `requests` library with a provided set of proxies to do web scraping. Paid webscraping services like [ZenRows](https://www.zenrows.com/) or [ScraperAPI](https://www.scraperapi.com/) offer a way to use their API via a set of proxies passed to `requests.get()` + +Example using `ProxyWebScraperDriver` directly: + +```python +import os +from griptape.drivers import ProxyWebScraperDriver + +query_params = [ + "markdown_response=true", + "js_render=false", + "premium_proxy=false", +] +proxy_url = f'http://{os.environ["ZENROWS_API_KEY"]}:{"&".join(query_params)}@proxy.zenrows.com:8001' + +driver = ProxyWebScraperDriver( + proxies={ + "http": proxy_url, + "https": proxy_url, + }, + params={ + "verify": False + } +) + +driver.scrape_url("https://griptape.ai") +``` + +### Markdownify !!! info This driver requires the `drivers-web-scraper-markdownify` [extra](../index.md#extras) and the @@ -64,7 +96,7 @@ agent = Agent( agent.run("List all email addresses on griptape.ai in a flat numbered markdown list.") ``` -## Trafilatura +### Trafilatura !!! info This driver requires the `drivers-web-scraper-trafilatura` [extra](../index.md#extras). diff --git a/docs/griptape-framework/drivers/web-search-drivers.md b/docs/griptape-framework/drivers/web-search-drivers.md new file mode 100644 index 000000000..18ba1e21c --- /dev/null +++ b/docs/griptape-framework/drivers/web-search-drivers.md @@ -0,0 +1,62 @@ +## Overview + +Web Search Drivers can be used to search for links from a search query. They are used by [WebSearch](../../reference/griptape/tools/web_search/tool.md) to provide its functionality. All Web Search Drivers implement the following methods: + +* `search()` searches the web and returns a [ListArtifact](../../reference/griptape/artifacts/list_artifact.md) that contains JSON-serializable [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s with the search results. + +## Google + +The [GoogleWebSearchDriver](../../reference/griptape/drivers/web_search/google_web_search_driver.md) uses the [Google Custom Search JSON API](https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list) for web searching. + +Example using `GoogleWebSearchDriver` directly: + +```python +import os +from griptape.drivers import GoogleWebSearchDriver + +driver = GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], +) + +driver.search("griptape ai") +``` + +Example of using `GoogleWebSearchDriver` with an agent: + +```python +import os +from griptape.drivers import GoogleWebSearchDriver +from griptape.tools import TaskMemoryClient, WebSearch +from griptape.structures import Agent + +agent = Agent( + tools=[ + WebSearch( + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + ), + ), + TaskMemoryClient(off_prompt=False), + ], +) +agent.run("Give me some websites with information about AI frameworks.") +``` + +## DuckDuckGo + +!!! info + This driver requires the `drivers-web-search-duckduckgo` [extra](../index.md#extras). + +The [DuckDuckGoWebSearchDriver](../../reference/griptape/drivers/web_search/duck_duck_go_web_search_driver.md) uses the [duckduckgo_search](https://github.com/deedy5/duckduckgo_search) SDK for web searching. + +Example of using `DuckDuckGoWebSearchDriver` directly: + +```python +from griptape.drivers import DuckDuckGoWebSearchDriver + +driver = DuckDuckGoWebSearchDriver() + +driver.search("griptape ai") +``` diff --git a/docs/griptape-framework/engines/image-query-engines.md b/docs/griptape-framework/engines/image-query-engines.md new file mode 100644 index 000000000..def6cbd5d --- /dev/null +++ b/docs/griptape-framework/engines/image-query-engines.md @@ -0,0 +1,25 @@ +## Image Query Engines + +The [Image Query Engine](../../reference/griptape/engines/image_query/image_query_engine.md) allows you to perform natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular [Image Query Driver](../drivers/image-query-drivers.md). + +All Image Query Drivers default to a `max_tokens` of 256. You can tune this value based on your use case and the [Image Query Driver](../drivers/image-query-drivers.md) you are providing. + +```python +from griptape.drivers import OpenAiImageQueryDriver +from griptape.engines import ImageQueryEngine +from griptape.loaders import ImageLoader + +driver = OpenAiImageQueryDriver( + model="gpt-4o", + max_tokens=256 +) + +engine = ImageQueryEngine( + image_query_driver=driver +) + +with open("tests/resources/mountain.png", "rb") as f: + image_artifact = ImageLoader().load(f.read()) + +engine.run("Describe the weather in the image", [image_artifact]) +``` diff --git a/docs/griptape-framework/engines/query-engines.md b/docs/griptape-framework/engines/query-engines.md deleted file mode 100644 index 38f5f6610..000000000 --- a/docs/griptape-framework/engines/query-engines.md +++ /dev/null @@ -1,52 +0,0 @@ -## Overview -Query engines are used to perform text queries against various modalities. - -## Vector - -Used to query vector storages. You can set a custom [prompt_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.prompt_driver) and [vector_store_driver](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.vector_store_driver). Uses [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) by default. - -Use the [upsert_text_artifact](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.upsert_text_artifact)s into vector storage with an optional `namespace`. - -Use the [VectorQueryEngine](../../reference/griptape/engines/query/vector_query_engine.md#griptape.engines.query.vector_query_engine.VectorQueryEngine.query) method to query the vector storage. - -```python -from griptape.drivers import OpenAiChatPromptDriver, LocalVectorStoreDriver, OpenAiEmbeddingDriver -from griptape.engines import VectorQueryEngine -from griptape.loaders import WebLoader - -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo"), - vector_store_driver=LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) -) - -engine.upsert_text_artifacts( - WebLoader().load("https://www.griptape.ai"), namespace="griptape" -) - -engine.query("what is griptape?", namespace="griptape") -``` - -## Image -The [Image Query Engine](../../reference/griptape/engines/image_query/image_query_engine.md) allows you to perform natural language queries on the contents of images. You can specify the provider and model used to query the image by providing the Engine with a particular [Image Query Driver](../drivers/image-query-drivers.md). - -All Image Query Drivers default to a `max_tokens` of 256. You can tune this value based on your use case and the [Image Query Driver](../drivers/image-query-drivers.md) you are providing. - -```python -from griptape.drivers import OpenAiImageQueryDriver -from griptape.engines import ImageQueryEngine -from griptape.loaders import ImageLoader - -driver = OpenAiImageQueryDriver( - model="gpt-4o", - max_tokens=256 -) - -engine = ImageQueryEngine( - image_query_driver=driver -) - -with open("tests/resources/mountain.png", "rb") as f: - image_artifact = ImageLoader().load(f.read()) - -engine.run("Describe the weather in the image", [image_artifact]) -``` diff --git a/docs/griptape-framework/engines/rag-engines.md b/docs/griptape-framework/engines/rag-engines.md new file mode 100644 index 000000000..9d71aaa80 --- /dev/null +++ b/docs/griptape-framework/engines/rag-engines.md @@ -0,0 +1,72 @@ +## RAG Engines + +!!! note + This section is a work in progress. + +`RagEngine` is an abstraction for implementing modular RAG pipelines. + +`RagContext` is a container object for passing around RAG context. + +### RAG Stages +- `QueryRagStage` is for parsing and expanding queries. +- `RetrievalRagStage` is for retrieving content. +- `ResponseRagStage` is for augmenting and generating outputs. + +### RAG Modules + +#### Query + +No modules implemented yet. + +#### Retrieval +- `TextRetrievalRagModule` is for retrieving text chunks. +- `TextLoaderRetrievalRagModule` is for retrieving data with text loaders in real time. +- `TextChunksRerankRagModule` is for re-ranking retrieved results. + +#### Response +- `MetadataBeforeResponseRagModule` is for appending metadata. +- `RulesetsBeforeResponseRagModule` is for appending rulesets. +- `PromptResponseRagModule` is for generating responses based on retrieved text chunks. +- `TextChunksResponseRagModule` is for responding with retrieved text chunks. +- `FootnotePromptResponseRagModule` is for responding with automatic footnotes from text chunk references. + +### Example + +```python +from griptape.artifacts import TextArtifact +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage + +vector_store = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + +artifacts = [ + TextArtifact("Griptape builds AI-powered applications that connect securely to your enterprise data and APIs."), + TextArtifact("Griptape Agents provide incredible power and flexibility when working with large language models.") +] +vector_store.upsert_text_artifacts({"griptape": artifacts}) + +engine = RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store, + query_params={ + "namespace": "griptape", + "top_n": 20 + } + ) + ] + ), + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) +) + +print( + engine.process_query("what are Griptape agents?").output.to_text() +) +``` \ No newline at end of file diff --git a/docs/griptape-framework/engines/summary-engines.md b/docs/griptape-framework/engines/summary-engines.md index 936c12a7c..e6960c0fb 100644 --- a/docs/griptape-framework/engines/summary-engines.md +++ b/docs/griptape-framework/engines/summary-engines.md @@ -4,7 +4,7 @@ Summary engines are used to summarize text and collections of [TextArtifact](../ ## Prompt -Used to summarize texts with LLMs. You can set a custom [prompt_driver](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.prompt_driver), [template_generator](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.template_generator), and [chunker](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.chunker). +Used to summarize texts with LLMs. You can set a custom [prompt_driver](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.prompt_driver), [system_template_generator](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.system_template_generator), [user_template_generator](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.user_template_generator), and [chunker](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.chunker). Use the [summarize_artifacts](../../reference/griptape/engines/summary/prompt_summary_engine.md#griptape.engines.summary.prompt_summary_engine.PromptSummaryEngine.summarize_artifacts) method to summarize a list of artifacts or [summarize_text](../../reference/griptape/engines/summary/base_summary_engine.md#griptape.engines.summary.base_summary_engine.BaseSummaryEngine.summarize_text) to summarize an arbitrary string. diff --git a/docs/griptape-framework/misc/events.md b/docs/griptape-framework/misc/events.md index 0921676fb..2d3645e94 100644 --- a/docs/griptape-framework/misc/events.md +++ b/docs/griptape-framework/misc/events.md @@ -244,9 +244,9 @@ from griptape.events import BaseEvent, StartPromptEvent, EventListener def handler(event: BaseEvent): if isinstance(event, StartPromptEvent): - print("Prompt Stack Inputs:") - for input in event.prompt_stack.inputs: - print(f"{input.role}: {input.content}") + print("Prompt Stack PromptStack:") + for message in event.prompt_stack.messages: + print(f"{message.role}: {message.content}") print("Final Prompt String:") print(event.prompt) @@ -259,7 +259,7 @@ agent.run("Write me a poem.") ``` ``` ... -Prompt Stack Inputs: +Prompt Stack Messages: system: user: Write me a poem. Final Prompt String: diff --git a/docs/griptape-framework/misc/tokenizers.md b/docs/griptape-framework/misc/tokenizers.md index 1920e912e..a6df1c388 100644 --- a/docs/griptape-framework/misc/tokenizers.md +++ b/docs/griptape-framework/misc/tokenizers.md @@ -1,7 +1,7 @@ ## Overview Tokenizers are used throughout Griptape to calculate the number of [tokens](https://learn.microsoft.com/en-us/semantic-kernel/prompt-engineering/tokens) in a piece of text. -They are particulary useful for ensuring that the LLM token limits are not exceeded. +They are particularly useful for ensuring that the LLM token limits are not exceeded. Tokenizers are a low level abstraction that you will rarely interact with directly. diff --git a/docs/griptape-framework/structures/agents.md b/docs/griptape-framework/structures/agents.md index 8737d2a59..b36db72d3 100644 --- a/docs/griptape-framework/structures/agents.md +++ b/docs/griptape-framework/structures/agents.md @@ -15,7 +15,7 @@ from griptape.structures import Agent agent = Agent( - input_template="Calculate the following: {{ args[0] }}", + input="Calculate the following: {{ args[0] }}", tools=[Calculator()] ) diff --git a/docs/griptape-framework/structures/config.md b/docs/griptape-framework/structures/config.md index d75354768..969163bf6 100644 --- a/docs/griptape-framework/structures/config.md +++ b/docs/griptape-framework/structures/config.md @@ -48,11 +48,19 @@ agent = Agent( The [Amazon Bedrock Structure Config](../../reference/griptape/config/amazon_bedrock_structure_config.md) provides default Drivers for Amazon Bedrock's APIs. ```python +import os +import boto3 from griptape.structures import Agent from griptape.config import AmazonBedrockStructureConfig agent = Agent( - config=AmazonBedrockStructureConfig() + config=AmazonBedrockStructureConfig( + session=boto3.Session( + region_name=os.environ["AWS_DEFAULT_REGION"], + aws_access_key_id=os.environ["AWS_ACCESS_KEY_ID"], + aws_secret_access_key=os.environ["AWS_SECRET_ACCESS_KEY"], + ) + ) ) ``` @@ -87,6 +95,19 @@ agent = Agent( ) ``` +#### Cohere + +The [Cohere Structure Config](../../reference/griptape/config/cohere_structure_config.md) provides default Drivers for Cohere's APIs. + + +```python +import os +from griptape.config import CohereStructureConfig +from griptape.structures import Agent + +agent = Agent(config=CohereStructureConfig(api_key=os.environ["COHERE_API_KEY"])) +``` + ### Custom Configs You can create your own [StructureConfig](../../reference/griptape/config/structure_config.md) by overriding relevant Drivers. diff --git a/docs/griptape-framework/structures/task-memory.md b/docs/griptape-framework/structures/task-memory.md index 219fd4412..24f0c6363 100644 --- a/docs/griptape-framework/structures/task-memory.md +++ b/docs/griptape-framework/structures/task-memory.md @@ -198,24 +198,25 @@ Because Task Memory splits up the storage and retrieval of data, you can use dif Here is an example where we use GPT-4 to orchestrate the Tools and store the data in Task Memory, and Amazon Bedrock's Titan model to query the raw content. In this example, GPT-4 _never_ sees the contents of the page, only that it was stored in Task Memory. Even the query results generated by the Titan model are stored in Task Memory so that the `FileManager` can save the results to disk without GPT-4 ever seeing them. - ```python from griptape.artifacts import TextArtifact from griptape.config import ( OpenAiStructureConfig, ) from griptape.drivers import ( - AmazonBedrockPromptDriver, - AmazonBedrockTitanEmbeddingDriver, LocalVectorStoreDriver, - OpenAiChatPromptDriver, + OpenAiChatPromptDriver, OpenAiEmbeddingDriver, ) -from griptape.engines import VectorQueryEngine +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.memory import TaskMemory from griptape.memory.task.storage import TextArtifactStorage from griptape.structures import Agent from griptape.tools import FileManager, TaskMemoryClient, WebScraper +vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + agent = Agent( config=OpenAiStructureConfig( prompt_driver=OpenAiChatPromptDriver(model="gpt-4"), @@ -223,21 +224,34 @@ agent = Agent( task_memory=TaskMemory( artifact_storages={ TextArtifact: TextArtifactStorage( - query_engine=VectorQueryEngine( - prompt_driver=AmazonBedrockPromptDriver( - model="amazon.titan-text-express-v1", - ), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=AmazonBedrockTitanEmbeddingDriver() + rag_engine=RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + + vector_store_driver=vector_store_driver, + query_params={ + "namespace": "griptape", + "count": 20 + } + ) + ] ), + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) ), - ), + retrieval_rag_module_name="VectorStoreRetrievalRagModule", + vector_store_driver=vector_store_driver + ) } ), tools=[ WebScraper(off_prompt=True), TaskMemoryClient(off_prompt=True, allowlist=["query"]), - FileManager(off_prompt=True), # FileManager returns an InfoArtifact which will not be stored in Task Memory regardless of the off_prompt setting + FileManager(off_prompt=True), ], ) @@ -247,27 +261,61 @@ agent.run( ``` ``` -[04/30/24 16:36:45] INFO ToolkitTask 3d3c5f5a98a44f32ad9533621c036604 - Input: According to this page https://en.wikipedia.org/wiki/Elden_Ring, find how many copies of Elden Ring have been sold and then save the - result to a file. -[04/30/24 16:36:52] INFO Subtask 61ec822bfe49472c9ed874fad07d13a1 - Thought: First, I need to scrape the content of the provided URL. Then, I will search the scraped content for the number of copies of Elden Ring that have been sold. Finally, I will save this information to a file. - - Actions: [{"name": "WebScraper", "path": "get_content", "input": {"values": {"url": "https://en.wikipedia.org/wiki/Elden_Ring"}}, "tag": "scrape_elden_ring"}] -[04/30/24 16:37:04] INFO Subtask 61ec822bfe49472c9ed874fad07d13a1 - Response: Output of "WebScraper.get_content" was stored in memory with memory_name "TaskMemory" and artifact_namespace "c7a01e8202e24869b7be559e0daff110" -[04/30/24 16:37:10] INFO Subtask 32f9cb73d8944e5ca36bd68a90e4f4b2 - Thought: Now that the webpage content is stored in memory, I need to query this memory to find the number of copies of Elden Ring that have been sold. - Actions: [{"tag": "query_sales", "name": "TaskMemoryClient", "path": "query", "input": {"values": {"memory_name": "TaskMemory", "artifact_namespace": "c7a01e8202e24869b7be559e0daff110", "query": "How many copies of Elden Ring have been sold?"}}}] -[04/30/24 16:37:18] INFO Subtask 32f9cb73d8944e5ca36bd68a90e4f4b2 - Response: Output of "TaskMemoryClient.query" was stored in memory with memory_name "TaskMemory" and artifact_namespace "f8dd40fb302a47d7862c8b76eeaf61c2" -[04/30/24 16:37:25] INFO Subtask 74a5fd392b044956842a56b76d09183e - Thought: Now that I have the number of copies sold stored in memory, I need to save this information to a file. - Actions: [{"tag": "save_sales", "name": "FileManager", "path": "save_memory_artifacts_to_disk", "input": {"values": {"dir_name": "sales_data", "file_name": "elden_ring_sales.txt", "memory_name": "TaskMemory", "artifact_namespace": "f8dd40fb302a47d7862c8b76eeaf61c2"}}}] - INFO Subtask 74a5fd392b044956842a56b76d09183e - Response: Successfully saved memory artifacts to disk -[04/30/24 16:37:27] INFO ToolkitTask 3d3c5f5a98a44f32ad9533621c036604 - Output: The number of copies of Elden Ring sold has been successfully saved to the file "elden_ring_sales.txt" in the "sales_data" directory. +[06/21/24 16:00:01] INFO ToolkitTask 17f30ac14701490c8ef71508f420ea9f + Input: Use this page + https://en.wikipedia.org/wiki/Elden_Ring to find + how many copies of Elden Ring have been sold, and + then save the result to a file. +[06/21/24 16:00:05] INFO Subtask cb06889205334ec9afd7e97f7f231ab5 + Thought: First, I need to scrape the content of the + provided URL to find the information about how many + copies of Elden Ring have been sold. Then, I will + save this information to a file. + + Actions: [{"name": "WebScraper", "path": + "get_content", "input": {"values": {"url": + "https://en.wikipedia.org/wiki/Elden_Ring"}}, + "tag": "scrape_elden_ring"}] +[06/21/24 16:00:12] INFO Subtask cb06889205334ec9afd7e97f7f231ab5 + Response: Output of "WebScraper.get_content" was + stored in memory with memory_name "TaskMemory" and + artifact_namespace + "7e48bcff0da94ad3b06aa4e173f8f37b" +[06/21/24 16:00:17] INFO Subtask 56102d42475d413299ce52a0230506b7 + Thought: Now that the webpage content is stored in + memory, I need to query this memory to find the + information about how many copies of Elden Ring + have been sold. + Actions: [{"tag": "query_sales", "name": + "TaskMemoryClient", "path": "query", "input": + {"values": {"memory_name": "TaskMemory", + "artifact_namespace": + "7e48bcff0da94ad3b06aa4e173f8f37b", "query": "How + many copies of Elden Ring have been sold?"}}}] +[06/21/24 16:00:19] INFO Subtask 56102d42475d413299ce52a0230506b7 + Response: Output of "TaskMemoryClient.query" was + stored in memory with memory_name "TaskMemory" and + artifact_namespace + "9ecf4d7b7d0c46149dfc46ba236f178e" +[06/21/24 16:00:25] INFO Subtask ed2921791dcf46b68c9d8d2f8dbeddbd + Thought: Now that I have the sales information + stored in memory, I need to save this information + to a file. + Actions: [{"tag": "save_sales_info", "name": + "FileManager", "path": + "save_memory_artifacts_to_disk", "input": + {"values": {"dir_name": "sales_info", "file_name": + "elden_ring_sales.txt", "memory_name": + "TaskMemory", "artifact_namespace": + "9ecf4d7b7d0c46149dfc46ba236f178e"}}}] + INFO Subtask ed2921791dcf46b68c9d8d2f8dbeddbd + Response: Successfully saved memory artifacts to + disk +[06/21/24 16:00:27] INFO ToolkitTask 17f30ac14701490c8ef71508f420ea9f + Output: The information about how many copies of + Elden Ring have been sold has been successfully + saved to the file "elden_ring_sales.txt" in the + "sales_info" directory. ``` ## Tools That Can Read From Task Memory diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index 53b1b702e..b839b2910 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -72,7 +72,7 @@ from griptape.structures import Agent agent = Agent() agent.add_task( # take the first argument from the agent `run` method - PromptTask("Respond to the users following request: {{ args[0] }}"), + PromptTask("Respond to the following request: {{ args[0] }}"), ) agent.run("Write me a haiku") @@ -80,7 +80,7 @@ agent.run("Write me a haiku") ``` [10/20/23 15:27:26] INFO PromptTask f5025c6352914e9f80ef730e5269985a - Input: Respond to the users following request: + Input: Respond to the following request: Write me a haiku [10/20/23 15:27:28] INFO PromptTask f5025c6352914e9f80ef730e5269985a Output: Gentle morning dew, @@ -88,6 +88,31 @@ agent.run("Write me a haiku") Day begins anew. ``` +If the model supports it, you can also pass image inputs: + +```python +from griptape.structures import Agent +from griptape.loaders import ImageLoader + +agent = Agent() +with open("tests/resources/mountain.jpg", "rb") as f: + image_artifact = ImageLoader().load(f.read()) + +agent.run(["What's in this image?", image_artifact]) +``` + +``` +[06/21/24 10:01:08] INFO PromptTask c229d1792da34ab1a7c45768270aada9 + Input: What's in this image? + + Media, type: image/jpeg, size: 82351 bytes +[06/21/24 10:01:12] INFO PromptTask c229d1792da34ab1a7c45768270aada9 + Output: The image depicts a stunning mountain landscape at sunrise or sunset. The sun is partially visible on the left side of the image, + casting a warm golden light over the scene. The mountains are covered with snow at their peaks, and a layer of clouds or fog is settled in the + valleys between them. The sky is a mix of warm colors near the horizon, transitioning to cooler blues higher up, with some scattered clouds + adding texture to the sky. The overall scene is serene and majestic, highlighting the natural beauty of the mountainous terrain. +``` + ## Toolkit Task To use [Griptape Tools](../../griptape-framework/tools/index.md), use a [Toolkit Task](../../reference/griptape/tasks/toolkit_task.md). @@ -350,40 +375,52 @@ agent.run( senses, bringing a revolution in technology. ``` -## Text Query Task +## RAG Task -To query text, use the [TextQueryTask](../../reference/griptape/tasks/text_query_task.md). -This Task takes a [Query Engine](../../griptape-framework/engines/query-engines.md), and a set of arguments specific to the engine. +To query text, use the [RagTask](../../reference/griptape/tasks/rag_task.md). +This task takes a [RAG Engine](../../griptape-framework/engines/rag-engines.md), and a set of arguments specific to the engine. ```python -from griptape.drivers import OpenAiChatPromptDriver from griptape.structures import Agent -from griptape.tasks import TextQueryTask -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver -from griptape.engines import VectorQueryEngine +from griptape.tasks import RagTask +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage # Initialize Embedding Driver and Vector Store Driver vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) -artifact = TextArtifact( - "Griptape builds AI-powered applications that connect securely to your enterprise data and APIs." - "Griptape Agents provide incredible power and flexibility when working with large language models." -) +artifacts = [ + TextArtifact("Griptape builds AI-powered applications that connect securely to your enterprise data and APIs."), + TextArtifact("Griptape Agents provide incredible power and flexibility when working with large language models.") +] +vector_store_driver.upsert_text_artifacts({"griptape": artifacts}) -# Create a VectorQueryEngine using the LocalVectorStoreDriver -vector_query_engine = VectorQueryEngine( - vector_store_driver=vector_store_driver, - prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo") -) -vector_query_engine.upsert_text_artifact(artifact=artifact) - -# Instantiate the agent and add TextQueryTask with the VectorQueryEngine +# Instantiate the agent and add RagTask with the RagEngine agent = Agent() agent.add_task( - TextQueryTask( - "Respond to the users following query: {{ args[0] }}", - query_engine=vector_query_engine, + RagTask( + "Respond to the following query: {{ args[0] }}", + rag_engine=RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, + query_params={ + "namespace": "griptape", + "top_n": 20 + } + ) + ] + ), + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) + ), ) ) @@ -391,21 +428,9 @@ agent.add_task( agent.run("Give me information about Griptape") ``` -``` -[10/20/23 15:32:39] INFO TextQueryTask a1d2eceab9204679b3f701f6ea821606 - Input: Respond to the users following query: Give - me information about Griptape -[10/20/23 15:32:41] INFO TextQueryTask a1d2eceab9204679b3f701f6ea821606 - Output: Griptape builds AI-powered applications - that connect securely to your enterprise data and - APIs. Griptape Agents provide incredible power and - flexibility when working with large language - models. -``` - ## Code Execution Task -To execute an arbitrary Python function, use the [CodeExecutionTask](../../reference/griptape/tasks/text_query_task.md). +To execute an arbitrary Python function, use the [CodeExecutionTask](../../reference/griptape/tasks/code_execution_task.md). This task takes a python function, and authors can elect to return a custom artifact. ```python @@ -518,7 +543,7 @@ engine = VariationImageGenerationEngine( with open("tests/resources/mountain.png", "rb") as f: image_artifact = ImageLoader().load(f.read()) -# Instatiate a pipeline. +# Instantiate a pipeline. pipeline = Pipeline() # Add a VariationImageGenerationTask to the pipeline. @@ -627,7 +652,7 @@ pipeline.run("An image of a mountain shrouded by clouds") ## Image Query Task -The [Image Query Task](../../reference/griptape/tasks/image_query_task.md) performs a natural language query on one or more input images. This Task uses an [Image Query Engine](../engines/query-engines.md#image) configured with an [Image Query Driver](../drivers/image-query-drivers.md) to perform the query. The functionality provided by this Task depend on the capabilities of the model provided by the Driver. +The [Image Query Task](../../reference/griptape/tasks/image_query_task.md) performs a natural language query on one or more input images. This Task uses an [Image Query Engine](../engines/image-query-engines.md) configured with an [Image Query Driver](../drivers/image-query-drivers.md) to perform the query. The functionality provided by this Task depend on the capabilities of the model provided by the Driver. This Task accepts two inputs: a query (represented by either a string or a [Text Artifact](../data/artifacts.md#textartifact)) and a list of [Image Artifacts](../data/artifacts.md#imageartifact) or a Callable returning these two values. @@ -677,7 +702,7 @@ import os from griptape.rules import Rule, Ruleset from griptape.structures import Agent, Pipeline from griptape.tasks import StructureRunTask -from griptape.drivers import LocalStructureRunDriver +from griptape.drivers import LocalStructureRunDriver, GoogleWebSearchDriver from griptape.tools import ( TaskMemoryClient, WebScraper, @@ -689,8 +714,10 @@ def build_researcher(): researcher = Agent( tools=[ WebSearch( - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + ), ), WebScraper( off_prompt=True, @@ -740,7 +767,7 @@ def build_researcher(): def build_writer(): writer = Agent( - input_template="Instructions: {{args[0]}}\nContext: {{args[1]}}", + input="Instructions: {{args[0]}}\nContext: {{args[1]}}", rulesets=[ Ruleset( name="Position", diff --git a/docs/griptape-tools/official-tools/date-time.md b/docs/griptape-tools/official-tools/date-time.md index 6ecf6e2a6..aa0c0cc55 100644 --- a/docs/griptape-tools/official-tools/date-time.md +++ b/docs/griptape-tools/official-tools/date-time.md @@ -12,9 +12,7 @@ agent = Agent( ) # Fetch the current date and time -agent.run({ - "description": "What is the current date and time?" -}) +agent.run("What is the current date and time?") ``` ``` [09/11/23 15:26:02] INFO Task d0bf49dacd8849e695494578a333f6cc diff --git a/docs/griptape-tools/official-tools/rag-client.md b/docs/griptape-tools/official-tools/rag-client.md new file mode 100644 index 000000000..6c8f9f17d --- /dev/null +++ b/docs/griptape-tools/official-tools/rag-client.md @@ -0,0 +1,51 @@ +The [RagClient](../../reference/griptape/tools/rag_client/tool.md) enables LLMs to query modular RAG engines. + +Here is an example of how it can be used with a local vector store driver: + +```python +from griptape.structures import Agent +from griptape.tasks import RagTask +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage + +# Initialize Embedding Driver and Vector Store Driver +vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) + +artifact = TextArtifact( + "Griptape builds AI-powered applications that connect securely to your enterprise data and APIs." + "Griptape Agents provide incredible power and flexibility when working with large language models." +) +vector_store_driver.upsert_text_artifact(artifact=artifact, namespace="griptape") + +# Instantiate the agent and add RagTask with the RagEngine +agent = Agent() +agent.add_task( + RagTask( + "Respond to the following query: {{ args[0] }}", + rag_engine=RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, + query_params={ + "namespace": "griptape", + "top_n": 20 + } + ) + ] + ), + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule( + prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") + ) + ) + ), + ) +) + +# Run the agent with a query string +agent.run("Give me information about Griptape") +``` diff --git a/docs/griptape-tools/official-tools/vector-store-client.md b/docs/griptape-tools/official-tools/vector-store-client.md index 5af8cee88..f3cab2065 100644 --- a/docs/griptape-tools/official-tools/vector-store-client.md +++ b/docs/griptape-tools/official-tools/vector-store-client.md @@ -1,30 +1,27 @@ -The [VectorStoreClient](../../reference/griptape/tools/vector_store_client/tool.md) enables LLMs to dynamically query task memory. +The [VectorStoreClient](../../reference/griptape/tools/vector_store_client/tool.md) enables LLMs to query vector stores. -Here is an example of how it can be used with the Pincone storage driver: +Here is an example of how it can be used with a local vector store driver: ```python from griptape.structures import Agent from griptape.tools import VectorStoreClient, TaskMemoryClient from griptape.loaders import WebLoader -from griptape.engines import VectorQueryEngine -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver -engine = VectorQueryEngine( - prompt_driver=OpenAiChatPromptDriver(model="gpt-3.5-turbo"), - vector_store_driver=LocalVectorStoreDriver( - embedding_driver=OpenAiEmbeddingDriver(), - ), +vector_store_driver = LocalVectorStoreDriver( + embedding_driver=OpenAiEmbeddingDriver(), ) -engine.upsert_text_artifacts( - WebLoader().load("https://www.griptape.ai"), - namespace="griptape" +vector_store_driver.upsert_text_artifacts( + { + "griptape": WebLoader().load("https://www.griptape.ai") + } ) vector_db = VectorStoreClient( description="This DB has information about the Griptape Python framework", - query_engine=engine, - namespace="griptape", + vector_store_driver=vector_store_driver, + query_params={"namespace": "griptape"}, off_prompt=True ) diff --git a/docs/griptape-tools/official-tools/web-search.md b/docs/griptape-tools/official-tools/web-search.md index 2e2ea276d..b30c76038 100644 --- a/docs/griptape-tools/official-tools/web-search.md +++ b/docs/griptape-tools/official-tools/web-search.md @@ -6,14 +6,17 @@ This tool enables LLMs to search the web. import os from griptape.tools import WebSearch from griptape.structures import Agent +from griptape.drivers import GoogleWebSearchDriver # Initialize the WebSearch tool with necessary parameters web_search_tool = WebSearch( - results_count=5, - google_api_lang="lang_en", - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], - google_api_country="us", + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], + search_id=os.environ["GOOGLE_API_SEARCH_ID"], + results_count=5, + language="en", + country="us", + ), ) # Set up an agent using the WebSearch tool diff --git a/griptape/artifacts/__init__.py b/griptape/artifacts/__init__.py index e57177ac4..00c19519f 100644 --- a/griptape/artifacts/__init__.py +++ b/griptape/artifacts/__init__.py @@ -3,6 +3,7 @@ from .info_artifact import InfoArtifact from .text_artifact import TextArtifact from .blob_artifact import BlobArtifact +from .boolean_artifact import BooleanArtifact from .csv_row_artifact import CsvRowArtifact from .list_artifact import ListArtifact from .media_artifact import MediaArtifact @@ -16,6 +17,7 @@ "InfoArtifact", "TextArtifact", "BlobArtifact", + "BooleanArtifact", "CsvRowArtifact", "ListArtifact", "MediaArtifact", diff --git a/griptape/artifacts/base_artifact.py b/griptape/artifacts/base_artifact.py index a7a1811ea..626e13f69 100644 --- a/griptape/artifacts/base_artifact.py +++ b/griptape/artifacts/base_artifact.py @@ -1,15 +1,20 @@ from __future__ import annotations from griptape.mixins import SerializableMixin -from typing import Any +from typing import Any, TYPE_CHECKING, Optional import json import uuid from abc import ABC, abstractmethod from attrs import define, field, Factory +if TYPE_CHECKING: + from griptape.common import Reference -@define() + +@define class BaseArtifact(SerializableMixin, ABC): id: str = field(default=Factory(lambda: uuid.uuid4().hex), kw_only=True, metadata={"serializable": True}) + reference: Optional[Reference] = field(default=None, kw_only=True, metadata={"serializable": True}) + meta: dict[str, Any] = field(factory=dict, kw_only=True, metadata={"serializable": True}) name: str = field( default=Factory(lambda self: self.id, takes_self=True), kw_only=True, metadata={"serializable": True} ) @@ -24,10 +29,7 @@ def value_to_bytes(cls, value: Any) -> bytes: @classmethod def value_to_dict(cls, value: Any) -> dict: - if isinstance(value, dict): - dict_value = value - else: - dict_value = json.loads(value) + dict_value = value if isinstance(value, dict) else json.loads(value) return {k: v for k, v in dict_value.items()} diff --git a/griptape/artifacts/boolean_artifact.py b/griptape/artifacts/boolean_artifact.py new file mode 100644 index 000000000..e7e440f45 --- /dev/null +++ b/griptape/artifacts/boolean_artifact.py @@ -0,0 +1,30 @@ +from __future__ import annotations +from typing import Union +from attrs import define, field +from griptape.artifacts import BaseArtifact + + +@define +class BooleanArtifact(BaseArtifact): + value: bool = field(converter=bool, metadata={"serializable": True}) + + @classmethod + def parse_bool(cls, value: Union[str, bool]) -> BooleanArtifact: + """ + Convert a string literal or bool to a BooleanArtifact. The string must be either "true" or "false" with any casing. + """ + if value is not None: + if isinstance(value, str): + if value.lower() == "true": + return BooleanArtifact(True) + elif value.lower() == "false": + return BooleanArtifact(False) + elif isinstance(value, bool): + return BooleanArtifact(value) + raise ValueError(f"Cannot convert '{value}' to BooleanArtifact") + + def __add__(self, other: BaseArtifact) -> BooleanArtifact: + raise ValueError("Cannot add BooleanArtifact with other artifacts") + + def __eq__(self, value: object) -> bool: + return self.value is value diff --git a/griptape/artifacts/media_artifact.py b/griptape/artifacts/media_artifact.py index 92cc0d9cd..2848ec1bb 100644 --- a/griptape/artifacts/media_artifact.py +++ b/griptape/artifacts/media_artifact.py @@ -29,7 +29,7 @@ class MediaArtifact(BlobArtifact): model: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) prompt: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) - def __attrs_post_init__(self): + def __attrs_post_init__(self) -> None: # Generating the name string requires attributes set by child classes. # This waits until all attributes are available before generating a name. if self.name == self.id: diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index 793bf24ad..26199a16c 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -58,10 +58,7 @@ def _chunk_recursively(self, chunk: str, current_separator: Optional[ChunkSepara # Iterate through the subchunks and calculate token counts. for index, subchunk in enumerate(subchunks): if index < len(subchunks): - if separator.is_prefix: - subchunk = separator.value + subchunk - else: - subchunk = subchunk + separator.value + subchunk = separator.value + subchunk if separator.is_prefix else subchunk + separator.value tokens_count += self.tokenizer.count_tokens(subchunk) diff --git a/griptape/common/__init__.py b/griptape/common/__init__.py new file mode 100644 index 000000000..6e357323a --- /dev/null +++ b/griptape/common/__init__.py @@ -0,0 +1,26 @@ +from .prompt_stack.contents.base_message_content import BaseMessageContent +from .prompt_stack.contents.base_delta_message_content import BaseDeltaMessageContent +from .prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent +from .prompt_stack.contents.text_message_content import TextMessageContent +from .prompt_stack.contents.image_message_content import ImageMessageContent + +from .prompt_stack.messages.base_message import BaseMessage +from .prompt_stack.messages.delta_message import DeltaMessage +from .prompt_stack.messages.message import Message + +from .prompt_stack.prompt_stack import PromptStack + +from .reference import Reference + +__all__ = [ + "BaseMessage", + "BaseDeltaMessageContent", + "BaseMessageContent", + "DeltaMessage", + "Message", + "TextDeltaMessageContent", + "TextMessageContent", + "ImageMessageContent", + "PromptStack", + "Reference", +] diff --git a/griptape/engines/query/__init__.py b/griptape/common/prompt_stack/__init__.py similarity index 100% rename from griptape/engines/query/__init__.py rename to griptape/common/prompt_stack/__init__.py diff --git a/tests/unit/engines/query/__init__.py b/griptape/common/prompt_stack/contents/__init__.py similarity index 100% rename from tests/unit/engines/query/__init__.py rename to griptape/common/prompt_stack/contents/__init__.py diff --git a/griptape/common/prompt_stack/contents/base_delta_message_content.py b/griptape/common/prompt_stack/contents/base_delta_message_content.py new file mode 100644 index 000000000..344f0bb7a --- /dev/null +++ b/griptape/common/prompt_stack/contents/base_delta_message_content.py @@ -0,0 +1,12 @@ +from __future__ import annotations + +from abc import ABC + +from attrs import define, field + +from griptape.mixins.serializable_mixin import SerializableMixin + + +@define +class BaseDeltaMessageContent(ABC, SerializableMixin): + index: int = field(kw_only=True, default=0, metadata={"serializable": True}) diff --git a/griptape/common/prompt_stack/contents/base_message_content.py b/griptape/common/prompt_stack/contents/base_message_content.py new file mode 100644 index 000000000..28a9e317e --- /dev/null +++ b/griptape/common/prompt_stack/contents/base_message_content.py @@ -0,0 +1,30 @@ +from __future__ import annotations +from abc import ABC +from collections.abc import Sequence +from typing import TYPE_CHECKING +from attrs import define, field +from griptape.mixins import SerializableMixin +from .base_delta_message_content import BaseDeltaMessageContent + +if TYPE_CHECKING: + from griptape.artifacts.base_artifact import BaseArtifact + + +@define +class BaseMessageContent(ABC, SerializableMixin): + artifact: BaseArtifact = field(metadata={"serializable": True}) + + def to_text(self) -> str: + return str(self.artifact) + + def __str__(self) -> str: + return self.artifact.to_text() + + def __bool__(self) -> bool: + return bool(self.artifact) + + def __len__(self) -> int: + return len(self.artifact) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> BaseMessageContent: ... diff --git a/griptape/common/prompt_stack/contents/image_message_content.py b/griptape/common/prompt_stack/contents/image_message_content.py new file mode 100644 index 000000000..0192a2cb4 --- /dev/null +++ b/griptape/common/prompt_stack/contents/image_message_content.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from collections.abc import Sequence + +from attrs import define, field + +from griptape.artifacts import ImageArtifact +from griptape.common import BaseDeltaMessageContent, BaseMessageContent + + +@define +class ImageMessageContent(BaseMessageContent): + artifact: ImageArtifact = field(metadata={"serializable": True}) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> ImageMessageContent: + raise NotImplementedError() diff --git a/griptape/common/prompt_stack/contents/text_delta_message_content.py b/griptape/common/prompt_stack/contents/text_delta_message_content.py new file mode 100644 index 000000000..ab5313df6 --- /dev/null +++ b/griptape/common/prompt_stack/contents/text_delta_message_content.py @@ -0,0 +1,9 @@ +from __future__ import annotations +from attrs import define, field + +from griptape.common import BaseDeltaMessageContent + + +@define +class TextDeltaMessageContent(BaseDeltaMessageContent): + text: str = field(metadata={"serializable": True}) diff --git a/griptape/common/prompt_stack/contents/text_message_content.py b/griptape/common/prompt_stack/contents/text_message_content.py new file mode 100644 index 000000000..1d7b2bd5b --- /dev/null +++ b/griptape/common/prompt_stack/contents/text_message_content.py @@ -0,0 +1,20 @@ +from __future__ import annotations + +from attrs import define, field +from collections.abc import Sequence + +from griptape.artifacts import TextArtifact +from griptape.common import BaseMessageContent, BaseDeltaMessageContent, TextDeltaMessageContent + + +@define +class TextMessageContent(BaseMessageContent): + artifact: TextArtifact = field(metadata={"serializable": True}) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> TextMessageContent: + text_deltas = [delta for delta in deltas if isinstance(delta, TextDeltaMessageContent)] + + artifact = TextArtifact(value="".join(delta.text for delta in text_deltas)) + + return cls(artifact=artifact) diff --git a/griptape/common/prompt_stack/messages/__init__.py b/griptape/common/prompt_stack/messages/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/common/prompt_stack/messages/base_message.py b/griptape/common/prompt_stack/messages/base_message.py new file mode 100644 index 000000000..3cc8e532a --- /dev/null +++ b/griptape/common/prompt_stack/messages/base_message.py @@ -0,0 +1,44 @@ +from __future__ import annotations + +from abc import ABC +from typing import Optional, Union +from attrs import Factory, define, field + + +from griptape.common import BaseMessageContent, BaseDeltaMessageContent +from griptape.mixins import SerializableMixin + + +@define +class BaseMessage(ABC, SerializableMixin): + @define + class Usage(SerializableMixin): + input_tokens: Optional[float] = field(kw_only=True, default=None, metadata={"serializable": True}) + output_tokens: Optional[float] = field(kw_only=True, default=None, metadata={"serializable": True}) + + @property + def total_tokens(self) -> float: + return (self.input_tokens or 0) + (self.output_tokens or 0) + + def __add__(self, other: BaseMessage.Usage) -> BaseMessage.Usage: + return BaseMessage.Usage( + input_tokens=(self.input_tokens or 0) + (other.input_tokens or 0), + output_tokens=(self.output_tokens or 0) + (other.output_tokens or 0), + ) + + USER_ROLE = "user" + ASSISTANT_ROLE = "assistant" + SYSTEM_ROLE = "system" + + content: list[Union[BaseMessageContent, BaseDeltaMessageContent]] = field(metadata={"serializable": True}) + role: str = field(kw_only=True, metadata={"serializable": True}) + usage: Usage = field(kw_only=True, default=Factory(lambda: BaseMessage.Usage()), metadata={"serializable": True}) + + def is_system(self) -> bool: + return self.role == self.SYSTEM_ROLE + + def is_user(self) -> bool: + return self.role == self.USER_ROLE + + def is_assistant(self) -> bool: + return self.role == self.ASSISTANT_ROLE diff --git a/griptape/common/prompt_stack/messages/delta_message.py b/griptape/common/prompt_stack/messages/delta_message.py new file mode 100644 index 000000000..7ff90b08f --- /dev/null +++ b/griptape/common/prompt_stack/messages/delta_message.py @@ -0,0 +1,15 @@ +from __future__ import annotations +from typing import Optional + +from attrs import define, field + +from griptape.common.prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent + + +from .base_message import BaseMessage + + +@define +class DeltaMessage(BaseMessage): + role: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) + content: Optional[TextDeltaMessageContent] = field(kw_only=True, default=None, metadata={"serializable": True}) diff --git a/griptape/common/prompt_stack/messages/message.py b/griptape/common/prompt_stack/messages/message.py new file mode 100644 index 000000000..fcf6750ea --- /dev/null +++ b/griptape/common/prompt_stack/messages/message.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact +from griptape.common import BaseMessageContent, TextMessageContent + +from .base_message import BaseMessage + + +@define +class Message(BaseMessage): + def __init__(self, content: str | list[BaseMessageContent], **kwargs: Any): + if isinstance(content, str): + content = [TextMessageContent(TextArtifact(value=content))] + self.__attrs_init__(content, **kwargs) # pyright: ignore[reportAttributeAccessIssue] + + content: list[BaseMessageContent] = field(metadata={"serializable": True}) + + @property + def value(self) -> Any: + return self.to_artifact().value + + def __str__(self) -> str: + return self.to_text() + + def to_text(self) -> str: + return "".join( + [content.artifact.to_text() for content in self.content if isinstance(content, TextMessageContent)] + ) + + def to_artifact(self) -> BaseArtifact: + if len(self.content) == 1: + return self.content[0].artifact + else: + return ListArtifact([content.artifact for content in self.content]) diff --git a/griptape/common/prompt_stack/prompt_stack.py b/griptape/common/prompt_stack/prompt_stack.py new file mode 100644 index 000000000..ce19696e3 --- /dev/null +++ b/griptape/common/prompt_stack/prompt_stack.py @@ -0,0 +1,56 @@ +from __future__ import annotations +from attrs import define, field + +from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact, ImageArtifact +from griptape.mixins import SerializableMixin +from griptape.common import Message, TextMessageContent, BaseMessageContent, ImageMessageContent + + +@define +class PromptStack(SerializableMixin): + messages: list[Message] = field(factory=list, kw_only=True, metadata={"serializable": True}) + + @property + def system_messages(self) -> list[Message]: + return [message for message in self.messages if message.is_system()] + + @property + def user_messages(self) -> list[Message]: + return [message for message in self.messages if message.is_user()] + + @property + def assistant_messages(self) -> list[Message]: + return [message for message in self.messages if message.is_assistant()] + + def add_message(self, artifact: str | BaseArtifact, role: str) -> Message: + new_content = self.__process_artifact(artifact) + + self.messages.append(Message(content=new_content, role=role)) + + return self.messages[-1] + + def add_system_message(self, artifact: str | BaseArtifact) -> Message: + return self.add_message(artifact, Message.SYSTEM_ROLE) + + def add_user_message(self, artifact: str | BaseArtifact) -> Message: + return self.add_message(artifact, Message.USER_ROLE) + + def add_assistant_message(self, artifact: str | BaseArtifact) -> Message: + return self.add_message(artifact, Message.ASSISTANT_ROLE) + + def __process_artifact(self, artifact: str | BaseArtifact) -> list[BaseMessageContent]: + if isinstance(artifact, str): + return [TextMessageContent(TextArtifact(artifact))] + elif isinstance(artifact, TextArtifact): + return [TextMessageContent(artifact)] + elif isinstance(artifact, ImageArtifact): + return [ImageMessageContent(artifact)] + elif isinstance(artifact, ListArtifact): + processed_contents = [self.__process_artifact(artifact) for artifact in artifact.value] + flattened_content = [ + sub_content for processed_content in processed_contents for sub_content in processed_content + ] + + return flattened_content + else: + raise ValueError(f"Unsupported artifact type: {type(artifact)}") diff --git a/griptape/common/reference.py b/griptape/common/reference.py new file mode 100644 index 000000000..d92c203f9 --- /dev/null +++ b/griptape/common/reference.py @@ -0,0 +1,14 @@ +import uuid +from typing import Optional +from attrs import define, field, Factory +from griptape.mixins import SerializableMixin + + +@define(kw_only=True) +class Reference(SerializableMixin): + id: str = field(default=Factory(lambda: uuid.uuid4().hex), metadata={"serializable": True}) + title: str = field(metadata={"serializable": True}) + authors: list[str] = field(factory=list, metadata={"serializable": True}) + source: Optional[str] = field(default=None, metadata={"serializable": True}) + year: Optional[str] = field(default=None, metadata={"serializable": True}) + url: Optional[str] = field(default=None, metadata={"serializable": True}) diff --git a/griptape/config/amazon_bedrock_structure_config.py b/griptape/config/amazon_bedrock_structure_config.py index 0fa807125..cdb685c76 100644 --- a/griptape/config/amazon_bedrock_structure_config.py +++ b/griptape/config/amazon_bedrock_structure_config.py @@ -1,5 +1,9 @@ +from __future__ import annotations +from typing import TYPE_CHECKING from attrs import Factory, define, field +from griptape.drivers import BasePromptDriver +from griptape.utils import import_optional_dependency from griptape.config import StructureConfig from griptape.drivers import ( AmazonBedrockImageGenerationDriver, @@ -8,49 +12,68 @@ AmazonBedrockTitanEmbeddingDriver, BaseEmbeddingDriver, BaseImageGenerationDriver, - BasePromptDriver, BaseVectorStoreDriver, BedrockClaudeImageQueryModelDriver, BedrockTitanImageGenerationModelDriver, LocalVectorStoreDriver, ) +if TYPE_CHECKING: + import boto3 -@define() + +@define class AmazonBedrockStructureConfig(StructureConfig): + session: boto3.Session = field( + default=Factory(lambda: import_optional_dependency("boto3").Session()), + kw_only=True, + metadata={"serializable": False}, + ) + prompt_driver: BasePromptDriver = field( default=Factory( - lambda: AmazonBedrockPromptDriver(model="anthropic.claude-3-5-sonnet-20240620-v1:0", stream=False) + lambda self: AmazonBedrockPromptDriver( + session=self.session, model="anthropic.claude-3-5-sonnet-20240620-v1:0" + ), + takes_self=True, ), + kw_only=True, + metadata={"serializable": True}, + ) + embedding_driver: BaseEmbeddingDriver = field( + default=Factory( + lambda self: AmazonBedrockTitanEmbeddingDriver(session=self.session, model="amazon.titan-embed-text-v1"), + takes_self=True, + ), + kw_only=True, metadata={"serializable": True}, ) image_generation_driver: BaseImageGenerationDriver = field( default=Factory( - lambda: AmazonBedrockImageGenerationDriver( + lambda self: AmazonBedrockImageGenerationDriver( + session=self.session, model="amazon.titan-image-generator-v1", image_generation_model_driver=BedrockTitanImageGenerationModelDriver(), - ) + ), + takes_self=True, ), + kw_only=True, metadata={"serializable": True}, ) image_query_driver: BaseImageGenerationDriver = field( default=Factory( - lambda: AmazonBedrockImageQueryDriver( + lambda self: AmazonBedrockImageQueryDriver( + session=self.session, model="anthropic.claude-3-5-sonnet-20240620-v1:0", image_query_model_driver=BedrockClaudeImageQueryModelDriver(), - ) + ), + takes_self=True, ), - metadata={"serializable": True}, - ) - embedding_driver: BaseEmbeddingDriver = field( - default=Factory(lambda: AmazonBedrockTitanEmbeddingDriver(model="amazon.titan-embed-text-v1")), + kw_only=True, metadata={"serializable": True}, ) vector_store_driver: BaseVectorStoreDriver = field( - default=Factory( - lambda: LocalVectorStoreDriver( - embedding_driver=AmazonBedrockTitanEmbeddingDriver(model="amazon.titan-embed-text-v1") - ) - ), + default=Factory(lambda self: LocalVectorStoreDriver(embedding_driver=self.embedding_driver), takes_self=True), + kw_only=True, metadata={"serializable": True}, ) diff --git a/griptape/config/google_structure_config.py b/griptape/config/google_structure_config.py index 744d08782..fc0548ff7 100644 --- a/griptape/config/google_structure_config.py +++ b/griptape/config/google_structure_config.py @@ -14,7 +14,9 @@ @define class GoogleStructureConfig(StructureConfig): prompt_driver: BasePromptDriver = field( - default=Factory(lambda: GooglePromptDriver(model="gemini-pro")), kw_only=True, metadata={"serializable": True} + default=Factory(lambda: GooglePromptDriver(model="gemini-1.5-pro")), + kw_only=True, + metadata={"serializable": True}, ) embedding_driver: BaseEmbeddingDriver = field( default=Factory(lambda: GoogleEmbeddingDriver(model="models/embedding-001")), diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 8e8128d7a..fa2934a38 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -39,6 +39,7 @@ from .vector.pgvector_vector_store_driver import PgVectorVectorStoreDriver from .vector.azure_mongodb_vector_store_driver import AzureMongoDbVectorStoreDriver from .vector.dummy_vector_store_driver import DummyVectorStoreDriver +from .vector.qdrant_vector_store_driver import QdrantVectorStoreDriver from .sql.base_sql_driver import BaseSqlDriver from .sql.amazon_redshift_sql_driver import AmazonRedshiftSqlDriver @@ -73,6 +74,11 @@ from .web_scraper.base_web_scraper_driver import BaseWebScraperDriver from .web_scraper.trafilatura_web_scraper_driver import TrafilaturaWebScraperDriver from .web_scraper.markdownify_web_scraper_driver import MarkdownifyWebScraperDriver +from .web_scraper.proxy_web_scraper_driver import ProxyWebScraperDriver + +from .web_search.base_web_search_driver import BaseWebSearchDriver +from .web_search.google_web_search_driver import GoogleWebSearchDriver +from .web_search.duck_duck_go_web_search_driver import DuckDuckGoWebSearchDriver from .event_listener.base_event_listener_driver import BaseEventListenerDriver from .event_listener.amazon_sqs_event_listener_driver import AmazonSqsEventListenerDriver @@ -85,6 +91,9 @@ from .file_manager.local_file_manager_driver import LocalFileManagerDriver from .file_manager.amazon_s3_file_manager_driver import AmazonS3FileManagerDriver +from .rerank.base_rerank_driver import BaseRerankDriver +from .rerank.cohere_rerank_driver import CohereRerankDriver + from .text_to_speech.base_text_to_speech_driver import BaseTextToSpeechDriver from .text_to_speech.dummy_text_to_speech_driver import DummyTextToSpeechDriver from .text_to_speech.elevenlabs_text_to_speech_driver import ElevenLabsTextToSpeechDriver @@ -136,6 +145,7 @@ "OpenSearchVectorStoreDriver", "AmazonOpenSearchVectorStoreDriver", "PgVectorVectorStoreDriver", + "QdrantVectorStoreDriver", "DummyVectorStoreDriver", "BaseSqlDriver", "AmazonRedshiftSqlDriver", @@ -163,6 +173,10 @@ "BaseWebScraperDriver", "TrafilaturaWebScraperDriver", "MarkdownifyWebScraperDriver", + "ProxyWebScraperDriver", + "BaseWebSearchDriver", + "GoogleWebSearchDriver", + "DuckDuckGoWebSearchDriver", "BaseEventListenerDriver", "AmazonSqsEventListenerDriver", "WebhookEventListenerDriver", @@ -172,6 +186,8 @@ "BaseFileManagerDriver", "LocalFileManagerDriver", "AmazonS3FileManagerDriver", + "BaseRerankDriver", + "CohereRerankDriver", "BaseTextToSpeechDriver", "DummyTextToSpeechDriver", "ElevenLabsTextToSpeechDriver", diff --git a/griptape/drivers/event_listener/base_event_listener_driver.py b/griptape/drivers/event_listener/base_event_listener_driver.py index b6d2d9b12..b433ed755 100644 --- a/griptape/drivers/event_listener/base_event_listener_driver.py +++ b/griptape/drivers/event_listener/base_event_listener_driver.py @@ -1,11 +1,9 @@ from __future__ import annotations - from abc import ABC, abstractmethod from concurrent import futures from logging import Logger - +from typing import Callable from attrs import Factory, define, field - from griptape.events import BaseEvent logger = Logger(__name__) @@ -13,7 +11,9 @@ @define class BaseEventListenerDriver(ABC): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) batched: bool = field(default=True, kw_only=True) batch_size: int = field(default=10, kw_only=True) @@ -24,7 +24,8 @@ def batch(self) -> list[dict]: return self._batch def publish_event(self, event: BaseEvent | dict, flush: bool = False) -> None: - self.futures_executor.submit(self._safe_try_publish_event, event, flush) + with self.futures_executor_fn() as executor: + executor.submit(self._safe_try_publish_event, event, flush) @abstractmethod def try_publish_event_payload(self, event_payload: dict) -> None: ... diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index bdb4d787c..e2d794f31 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -55,7 +55,7 @@ def try_load_file(self, path: str) -> bytes: return response["Body"].read() except botocore.exceptions.ClientError as e: if e.response["Error"]["Code"] in {"NoSuchKey", "404"}: - raise FileNotFoundError + raise FileNotFoundError from e else: raise e diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index 56f19b3cc..9b8fe8325 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -12,7 +12,7 @@ class BaseFileManagerDriver(ABC): Attributes: default_loader: The default loader to use for loading file contents into artifacts. - loaders: Dictionary of file extension specifc loaders to use for loading file contents into artifacts. + loaders: Dictionary of file extension specific loaders to use for loading file contents into artifacts. """ default_loader: loaders.BaseLoader = field(default=Factory(lambda: loaders.BlobLoader()), kw_only=True) @@ -82,11 +82,8 @@ def save_file(self, path: str, value: bytes | str) -> InfoArtifact | ErrorArtifa encoding = None if loader is None else loader.encoding if isinstance(value, str): - if encoding is None: - value = value.encode() - else: - value = value.encode(encoding=encoding) - elif isinstance(value, bytearray) or isinstance(value, memoryview): + value = value.encode() if encoding is None else value.encode(encoding=encoding) + elif isinstance(value, (bytearray, memoryview)): raise ValueError(f"Unsupported type: {type(value)}") self.try_save_file(path, value) diff --git a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py index 2edb9f862..b5a4b7e3b 100644 --- a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py +++ b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py @@ -122,6 +122,6 @@ def _make_request(self, request: dict) -> bytes: try: image_bytes = self.image_generation_model_driver.get_generated_image(response_body) except Exception as e: - raise ValueError(f"Inpainting generation failed: {e}") + raise ValueError(f"Inpainting generation failed: {e}") from e return image_bytes diff --git a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py index eabe9d27e..e91cbbedc 100644 --- a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py +++ b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py @@ -32,4 +32,4 @@ def try_query(self, query: str, images: list[ImageArtifact]) -> TextArtifact: try: return self.image_query_model_driver.process_output(response_body) except Exception as e: - raise ValueError(f"Output is unable to be processed as returned {e}") + raise ValueError(f"Output is unable to be processed as returned {e}") from e diff --git a/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py b/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py index 87c3667fe..36f62c0e5 100644 --- a/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py @@ -16,6 +16,8 @@ class AmazonDynamoDbConversationMemoryDriver(BaseConversationMemoryDriver): partition_key: str = field(kw_only=True, metadata={"serializable": True}) value_attribute_key: str = field(kw_only=True, metadata={"serializable": True}) partition_key_value: str = field(kw_only=True, metadata={"serializable": True}) + sort_key: Optional[str] = field(default=None, metadata={"serializable": True}) + sort_key_value: Optional[str | int] = field(default=None, metadata={"serializable": True}) table: Any = field(init=False) @@ -26,14 +28,14 @@ def __attrs_post_init__(self) -> None: def store(self, memory: BaseConversationMemory) -> None: self.table.update_item( - Key={self.partition_key: self.partition_key_value}, + Key=self._get_key(), UpdateExpression="set #attr = :value", ExpressionAttributeNames={"#attr": self.value_attribute_key}, ExpressionAttributeValues={":value": memory.to_json()}, ) def load(self) -> Optional[BaseConversationMemory]: - response = self.table.get_item(Key={self.partition_key: self.partition_key_value}) + response = self.table.get_item(Key=self._get_key()) if "Item" in response and self.value_attribute_key in response["Item"]: memory_value = response["Item"][self.value_attribute_key] @@ -45,3 +47,11 @@ def load(self) -> Optional[BaseConversationMemory]: return memory else: return None + + def _get_key(self) -> dict[str, str | int]: + key: dict[str, str | int] = {self.partition_key: self.partition_key_value} + + if self.sort_key is not None and self.sort_key_value is not None: + key[self.sort_key] = self.sort_key_value + + return key diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 849ed0901..21d81724d 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -6,6 +6,14 @@ from attrs import Factory, define, field from griptape.artifacts import TextArtifact +from griptape.common import ( + DeltaMessage, + Message, + TextDeltaMessageContent, + BaseMessageContent, + TextMessageContent, + ImageMessageContent, +) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AmazonBedrockTokenizer, BaseTokenizer from griptape.utils import import_optional_dependency @@ -13,7 +21,7 @@ if TYPE_CHECKING: import boto3 - from griptape.utils import PromptStack + from griptape.common import PromptStack @define @@ -27,44 +35,54 @@ class AmazonBedrockPromptDriver(BasePromptDriver): default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: response = self.bedrock_client.converse(**self._base_params(prompt_stack)) + usage = response["usage"] output_message = response["output"]["message"] - output_content = output_message["content"][0]["text"] - return TextArtifact(output_content) + return Message( + content=[TextMessageContent(TextArtifact(content["text"])) for content in output_message["content"]], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=usage["inputTokens"], output_tokens=usage["outputTokens"]), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: response = self.bedrock_client.converse_stream(**self._base_params(prompt_stack)) stream = response.get("stream") if stream is not None: for event in stream: if "contentBlockDelta" in event: - yield TextArtifact(event["contentBlockDelta"]["delta"]["text"]) + content_block_delta = event["contentBlockDelta"] + yield DeltaMessage( + content=TextDeltaMessageContent( + content_block_delta["delta"]["text"], index=content_block_delta["contentBlockIndex"] + ) + ) + elif "metadata" in event: + usage = event["metadata"]["usage"] + yield DeltaMessage( + usage=DeltaMessage.Usage(input_tokens=usage["inputTokens"], output_tokens=usage["outputTokens"]) + ) else: raise Exception("model response is empty") - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - content = [{"text": prompt_input.content}] - - if prompt_input.is_system(): - return {"text": prompt_input.content} - elif prompt_input.is_assistant(): - return {"role": "assistant", "content": content} - else: - return {"role": "user", "content": content} + def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: + return [ + { + "role": self.__to_role(message), + "content": [self.__prompt_stack_content_message_content(content) for content in message.content], + } + for message in messages + ] def _base_params(self, prompt_stack: PromptStack) -> dict: - system_messages = [ - self._prompt_stack_input_to_message(input) - for input in prompt_stack.inputs - if input.is_system() and input.content - ] - messages = [ - self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs if not input.is_system() - ] + system_messages = [{"text": message.to_text()} for message in prompt_stack.system_messages] + + messages = self._prompt_stack_messages_to_messages( + [message for message in prompt_stack.messages if not message.is_system()] + ) return { "modelId": self.model, @@ -73,3 +91,17 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "inferenceConfig": {"temperature": self.temperature}, "additionalModelRequestFields": self.additional_model_request_fields, } + + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"text": content.artifact.to_text()} + elif isinstance(content, ImageMessageContent): + return {"image": {"format": content.artifact.format, "source": {"bytes": content.artifact.value}}} + else: + raise ValueError(f"Unsupported content type: {type(content)}") + + def __to_role(self, message: Message) -> str: + if message.is_assistant(): + return "assistant" + else: + return "user" diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 18f8e4b77..dacaa62b0 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -7,14 +7,15 @@ from attrs import Factory, define, field from griptape.artifacts import TextArtifact -from griptape.drivers.prompt.base_prompt_driver import BasePromptDriver +from griptape.common import PromptStack, Message, TextMessageContent, DeltaMessage +from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: import boto3 - from griptape.utils import PromptStack + from griptape.common import PromptStack @define @@ -40,8 +41,11 @@ def validate_stream(self, _, stream): if stream: raise ValueError("streaming is not supported") - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - payload = {"inputs": self._to_model_input(prompt_stack), "parameters": self._to_model_params(prompt_stack)} + def try_run(self, prompt_stack: PromptStack) -> Message: + payload = { + "inputs": self.prompt_stack_to_string(prompt_stack), + "parameters": {**self._base_params(prompt_stack)}, + } response = self.sagemaker_client.invoke_endpoint( EndpointName=self.endpoint, @@ -59,31 +63,28 @@ def try_run(self, prompt_stack: PromptStack) -> TextArtifact: if isinstance(decoded_body, list): if decoded_body: - return TextArtifact(decoded_body[0]["generated_text"]) + generated_text = decoded_body[0]["generated_text"] else: raise ValueError("model response is empty") else: - return TextArtifact(decoded_body["generated_text"]) - - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - raise NotImplementedError("streaming is not supported") + generated_text = decoded_body["generated_text"] - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - return {"role": prompt_input.role, "content": prompt_input.content} + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + output_tokens = len(self.tokenizer.tokenizer.encode(generated_text)) - def _to_model_input(self, prompt_stack: PromptStack) -> str: - prompt = self.tokenizer.tokenizer.apply_chat_template( - [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], - tokenize=False, - add_generation_prompt=True, + return Message( + content=[TextMessageContent(TextArtifact(generated_text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), ) - if isinstance(prompt, str): - return prompt - else: - raise ValueError("Invalid output type.") + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: + raise NotImplementedError("streaming is not supported") - def _to_model_params(self, prompt_stack: PromptStack) -> dict: + def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: + return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) + + def _base_params(self, prompt_stack: PromptStack) -> dict: return { "temperature": self.temperature, "max_new_tokens": self.max_tokens, @@ -92,3 +93,21 @@ def _to_model_params(self, prompt_stack: PromptStack) -> dict: "stop_strings": self.tokenizer.stop_sequences, "return_full_text": False, } + + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + messages = [] + + for message in prompt_stack.messages: + messages.append({"role": message.role, "content": message.to_text()}) + + return messages + + def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: + messages = self._prompt_stack_to_messages(prompt_stack) + + tokens = self.tokenizer.tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=True) + + if isinstance(tokens, list): + return tokens + else: + raise ValueError("Invalid output type.") diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index b74a9d5f6..2c338c84c 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -1,11 +1,27 @@ from __future__ import annotations -from typing import Optional, Any + from collections.abc import Iterator -from attrs import define, field, Factory +from typing import Any, Optional, TYPE_CHECKING + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack, import_optional_dependency +from griptape.common import ( + BaseMessageContent, + DeltaMessage, + TextDeltaMessageContent, + ImageMessageContent, + PromptStack, + Message, + TextMessageContent, +) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AnthropicTokenizer, BaseTokenizer +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from anthropic.types import ContentBlockDeltaEvent + from anthropic.types import ContentBlock @define @@ -32,42 +48,37 @@ class AnthropicPromptDriver(BasePromptDriver): top_k: int = field(default=250, kw_only=True, metadata={"serializable": True}) max_tokens: int = field(default=1000, kw_only=True, metadata={"serializable": True}) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: response = self.client.messages.create(**self._base_params(prompt_stack)) - return TextArtifact(value=response.content[0].text) - - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - response = self.client.messages.create(**self._base_params(prompt_stack), stream=True) + return Message( + content=[self.__message_content_to_prompt_stack_content(content) for content in response.content], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=response.usage.input_tokens, output_tokens=response.usage.output_tokens), + ) - for chunk in response: - if chunk.type == "content_block_delta": - yield TextArtifact(value=chunk.delta.text) + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: + events = self.client.messages.create(**self._base_params(prompt_stack), stream=True) - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - content = prompt_input.content + for event in events: + if event.type == "content_block_delta": + yield DeltaMessage(content=self.__message_content_delta_to_prompt_stack_content_delta(event)) + elif event.type == "message_start": + yield DeltaMessage(usage=DeltaMessage.Usage(input_tokens=event.message.usage.input_tokens)) + elif event.type == "message_delta": + yield DeltaMessage(usage=DeltaMessage.Usage(output_tokens=event.usage.output_tokens)) - if prompt_input.is_system(): - return {"role": "system", "content": content} - elif prompt_input.is_assistant(): - return {"role": "assistant", "content": content} - else: - return {"role": "user", "content": content} - - def _prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> dict: - messages = [ - self._prompt_stack_input_to_message(prompt_input) - for prompt_input in prompt_stack.inputs - if not prompt_input.is_system() - ] - system = next((self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs if i.is_system()), None) - - if system is None: - return {"messages": messages} - else: - return {"messages": messages, "system": system["content"]} + def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: + return [{"role": self.__to_role(message), "content": self.__to_content(message)} for message in messages] def _base_params(self, prompt_stack: PromptStack) -> dict: + messages = self._prompt_stack_messages_to_messages( + [message for message in prompt_stack.messages if not message.is_system()] + ) + + system_messages = prompt_stack.system_messages + system_message = system_messages[0].to_text() if system_messages else None + return { "model": self.model, "temperature": self.temperature, @@ -75,5 +86,45 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "top_p": self.top_p, "top_k": self.top_k, "max_tokens": self.max_tokens, - **self._prompt_stack_to_model_input(prompt_stack), + "messages": messages, + **({"system": system_message} if system_message else {}), } + + def __to_role(self, message: Message) -> str: + if message.is_assistant(): + return "assistant" + else: + return "user" + + def __to_content(self, message: Message) -> str | list[dict]: + if all(isinstance(content, TextMessageContent) for content in message.content): + return message.to_text() + else: + return [self.__prompt_stack_content_message_content(content) for content in message.content] + + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"type": "text", "text": content.artifact.to_text()} + elif isinstance(content, ImageMessageContent): + return { + "type": "image", + "source": {"type": "base64", "media_type": content.artifact.mime_type, "data": content.artifact.base64}, + } + else: + raise ValueError(f"Unsupported prompt content type: {type(content)}") + + def __message_content_to_prompt_stack_content(self, content: ContentBlock) -> BaseMessageContent: + if content.type == "text": + return TextMessageContent(TextArtifact(content.text)) + else: + raise ValueError(f"Unsupported message content type: {content.type}") + + def __message_content_delta_to_prompt_stack_content_delta( + self, content_delta: ContentBlockDeltaEvent + ) -> TextDeltaMessageContent: + index = content_delta.index + + if content_delta.delta.type == "text_delta": + return TextDeltaMessageContent(content_delta.delta.text, index=index) + else: + raise ValueError(f"Unsupported message content delta type : {content_delta.delta.type}") diff --git a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py index 41c91cb65..64145b1a9 100644 --- a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py @@ -1,6 +1,6 @@ from attrs import define, field, Factory from typing import Callable, Optional -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.drivers import OpenAiChatPromptDriver import openai @@ -44,6 +44,10 @@ class AzureOpenAiChatPromptDriver(OpenAiChatPromptDriver): def _base_params(self, prompt_stack: PromptStack) -> dict: params = super()._base_params(prompt_stack) # TODO: Add `seed` parameter once Azure supports it. - del params["seed"] + if "seed" in params: + del params["seed"] + # TODO: Add `stream_options` parameter once Azure supports it. + if "stream_options" in params: + del params["stream_options"] return params diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 9ef076dbc..b499179ed 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -1,22 +1,30 @@ from __future__ import annotations + from abc import ABC, abstractmethod -from typing import TYPE_CHECKING, Optional from collections.abc import Iterator -from attrs import define, field, Factory -from griptape.events import StartPromptEvent, FinishPromptEvent, CompletionChunkEvent -from griptape.mixins.serializable_mixin import SerializableMixin -from griptape.utils import PromptStack -from griptape.mixins import ExponentialBackoffMixin +from typing import TYPE_CHECKING, Optional + +from attrs import Factory, define, field + +from griptape.common import ( + BaseDeltaMessageContent, + DeltaMessage, + TextDeltaMessageContent, + PromptStack, + Message, + TextMessageContent, +) +from griptape.events import CompletionChunkEvent, FinishPromptEvent, StartPromptEvent +from griptape.mixins import ExponentialBackoffMixin, SerializableMixin from griptape.tokenizers import BaseTokenizer -from griptape.artifacts import TextArtifact if TYPE_CHECKING: from griptape.structures import Structure -@define +@define(kw_only=True) class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): - """Base class for Prompt Drivers. + """Base class for the Prompt Drivers. Attributes: temperature: The temperature to use for the completion. @@ -29,50 +37,35 @@ class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): stream: Whether to stream the completion or not. `CompletionChunkEvent`s will be published to the `Structure` if one is provided. """ - temperature: float = field(default=0.1, kw_only=True, metadata={"serializable": True}) - max_tokens: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) - structure: Optional[Structure] = field(default=None, kw_only=True) - ignored_exception_types: tuple[type[Exception], ...] = field( - default=Factory(lambda: (ImportError, ValueError)), kw_only=True - ) + temperature: float = field(default=0.1, metadata={"serializable": True}) + max_tokens: Optional[int] = field(default=None, metadata={"serializable": True}) + structure: Optional[Structure] = field(default=None) + ignored_exception_types: tuple[type[Exception], ...] = field(default=Factory(lambda: (ImportError, ValueError))) model: str = field(metadata={"serializable": True}) tokenizer: BaseTokenizer - stream: bool = field(default=False, kw_only=True, metadata={"serializable": True}) + stream: bool = field(default=False, metadata={"serializable": True}) def before_run(self, prompt_stack: PromptStack) -> None: if self.structure: - self.structure.publish_event( - StartPromptEvent( - model=self.model, - token_count=self.tokenizer.count_tokens(self.prompt_stack_to_string(prompt_stack)), - prompt_stack=prompt_stack, - prompt=self.prompt_stack_to_string(prompt_stack), - ) - ) + self.structure.publish_event(StartPromptEvent(model=self.model, prompt_stack=prompt_stack)) - def after_run(self, result: TextArtifact) -> None: + def after_run(self, result: Message) -> None: if self.structure: self.structure.publish_event( FinishPromptEvent( - model=self.model, result=result.value, token_count=self.tokenizer.count_tokens(result.value) + model=self.model, + result=result.value, + input_token_count=result.usage.input_tokens, + output_token_count=result.usage.output_tokens, ) ) - def run(self, prompt_stack: PromptStack) -> TextArtifact: + def run(self, prompt_stack: PromptStack) -> Message: for attempt in self.retrying(): with attempt: self.before_run(prompt_stack) - if self.stream: - tokens = [] - completion_chunks = self.try_stream(prompt_stack) - for chunk in completion_chunks: - self.structure.publish_event(CompletionChunkEvent(token=chunk.value)) - tokens.append(chunk.value) - result = TextArtifact(value="".join(tokens).strip()) - else: - result = self.try_run(prompt_stack) - result.value = result.value.strip() + result = self.__process_stream(prompt_stack) if self.stream else self.__process_run(prompt_stack) self.after_run(result) @@ -92,20 +85,59 @@ def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: """ prompt_lines = [] - for i in prompt_stack.inputs: + for i in prompt_stack.messages: + content = i.to_text() if i.is_user(): - prompt_lines.append(f"User: {i.content}") + prompt_lines.append(f"User: {content}") elif i.is_assistant(): - prompt_lines.append(f"Assistant: {i.content}") + prompt_lines.append(f"Assistant: {content}") else: - prompt_lines.append(i.content) + prompt_lines.append(content) prompt_lines.append("Assistant:") return "\n\n".join(prompt_lines) @abstractmethod - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: ... + def try_run(self, prompt_stack: PromptStack) -> Message: ... @abstractmethod - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: ... + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: ... + + def __process_run(self, prompt_stack: PromptStack) -> Message: + result = self.try_run(prompt_stack) + + return result + + def __process_stream(self, prompt_stack: PromptStack) -> Message: + delta_contents: dict[int, list[BaseDeltaMessageContent]] = {} + usage = DeltaMessage.Usage() + + # Aggregate all content deltas from the stream + deltas = self.try_stream(prompt_stack) + for delta in deltas: + usage += delta.usage + + if delta.content is not None: + if delta.content.index in delta_contents: + delta_contents[delta.content.index].append(delta.content) + else: + delta_contents[delta.content.index] = [delta.content] + + if isinstance(delta.content, TextDeltaMessageContent): + self.structure.publish_event(CompletionChunkEvent(token=delta.content.text)) + + # Build a complete content from the content deltas + content = [] + for deltas in delta_contents.values(): + text_deltas = [delta for delta in deltas if isinstance(delta, TextDeltaMessageContent)] + if text_deltas: + content.append(TextMessageContent.from_deltas(text_deltas)) + + result = Message( + content=content, + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens), + ) + + return result diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index 3ff2c9e89..b00abd855 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -4,14 +4,23 @@ from attrs import define, field, Factory from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver -from griptape.utils import PromptStack, import_optional_dependency -from griptape.tokenizers import BaseTokenizer, CohereTokenizer +from griptape.tokenizers import CohereTokenizer +from griptape.common import ( + PromptStack, + Message, + DeltaMessage, + TextMessageContent, + BaseMessageContent, + TextDeltaMessageContent, +) +from griptape.utils import import_optional_dependency +from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: from cohere import Client -@define +@define(kw_only=True) class CoherePromptDriver(BasePromptDriver): """ Attributes: @@ -20,41 +29,57 @@ class CoherePromptDriver(BasePromptDriver): client: Custom `cohere.Client`. """ - api_key: str = field(kw_only=True, metadata={"serializable": False}) - model: str = field(kw_only=True, metadata={"serializable": True}) + api_key: str = field(metadata={"serializable": False}) + model: str = field(metadata={"serializable": True}) client: Client = field( - default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True), - kw_only=True, + default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True) ) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True), - kw_only=True, + default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True) ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: result = self.client.chat(**self._base_params(prompt_stack)) + usage = result.meta.tokens - return TextArtifact(value=result.text) + return Message( + content=[TextMessageContent(TextArtifact(result.text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: result = self.client.chat_stream(**self._base_params(prompt_stack)) for event in result: if event.event_type == "text-generation": - yield TextArtifact(value=event.text) + yield DeltaMessage(content=TextDeltaMessageContent(event.text, index=0)) + elif event.event_type == "stream-end": + usage = event.response.meta.tokens - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - if prompt_input.is_system(): - return {"role": "SYSTEM", "text": prompt_input.content} - elif prompt_input.is_user(): - return {"role": "USER", "text": prompt_input.content} - else: - return {"role": "ASSISTANT", "text": prompt_input.content} + yield DeltaMessage( + usage=DeltaMessage.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens) + ) + + def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: + return [ + { + "role": self.__to_role(message), + "content": [self.__prompt_stack_content_message_content(content) for content in message.content], + } + for message in messages + ] def _base_params(self, prompt_stack: PromptStack) -> dict: - user_message = prompt_stack.inputs[-1].content + last_input = prompt_stack.messages[-1] + user_message = last_input.to_text() - history_messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs[:-1]] + history_messages = self._prompt_stack_messages_to_messages( + [message for message in prompt_stack.messages[:-1] if not message.is_system()] + ) + + system_messages = prompt_stack.system_messages + preamble = system_messages[0].to_text() if system_messages else None return { "message": user_message, @@ -62,4 +87,19 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "temperature": self.temperature, "stop_sequences": self.tokenizer.stop_sequences, "max_tokens": self.max_tokens, + **({"preamble": preamble} if preamble else {}), } + + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"text": content.artifact.to_text()} + else: + raise ValueError(f"Unsupported content type: {type(content)}") + + def __to_role(self, message: Message) -> str: + if message.is_system(): + return "SYSTEM" + elif message.is_user(): + return "USER" + else: + return "CHATBOT" diff --git a/griptape/drivers/prompt/dummy_prompt_driver.py b/griptape/drivers/prompt/dummy_prompt_driver.py index a55ecd4fe..72757624d 100644 --- a/griptape/drivers/prompt/dummy_prompt_driver.py +++ b/griptape/drivers/prompt/dummy_prompt_driver.py @@ -1,10 +1,12 @@ +from __future__ import annotations from collections.abc import Iterator -from attrs import field, Factory, define -from griptape.tokenizers import DummyTokenizer + +from attrs import Factory, define, field + +from griptape.common import PromptStack, Message, DeltaMessage from griptape.drivers import BasePromptDriver -from griptape.artifacts import TextArtifact from griptape.exceptions import DummyException -from griptape.utils.prompt_stack import PromptStack +from griptape.tokenizers import DummyTokenizer @define @@ -12,11 +14,8 @@ class DummyPromptDriver(BasePromptDriver): model: None = field(init=False, default=None, kw_only=True) tokenizer: DummyTokenizer = field(default=Factory(lambda: DummyTokenizer()), kw_only=True) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: raise DummyException(__class__.__name__, "try_run") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: raise DummyException(__class__.__name__, "try_stream") - - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - raise DummyException(__class__.__name__, "_prompt_stack_input_to_message") diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 67bc19e24..ff4b07a93 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -1,15 +1,27 @@ from __future__ import annotations + from collections.abc import Iterator -from typing import TYPE_CHECKING, Optional, Any -from attrs import define, field, Factory -from griptape.utils import PromptStack, import_optional_dependency +from typing import TYPE_CHECKING, Any, Optional + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact +from griptape.common import ( + BaseMessageContent, + DeltaMessage, + TextDeltaMessageContent, + ImageMessageContent, + PromptStack, + Message, + TextMessageContent, +) from griptape.drivers import BasePromptDriver -from griptape.tokenizers import GoogleTokenizer, BaseTokenizer +from griptape.tokenizers import BaseTokenizer, GoogleTokenizer +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from google.generativeai import GenerativeModel - from google.generativeai.types import ContentDict + from google.generativeai.types import ContentDict, GenerateContentResponse @define @@ -33,12 +45,12 @@ class GooglePromptDriver(BasePromptDriver): top_p: Optional[float] = field(default=None, kw_only=True, metadata={"serializable": True}) top_k: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig - inputs = self._prompt_stack_to_model_input(prompt_stack) - response = self.model_client.generate_content( - inputs, + messages = self._prompt_stack_to_messages(prompt_stack) + response: GenerateContentResponse = self.model_client.generate_content( + messages, generation_config=GenerationConfig( stop_sequences=self.tokenizer.stop_sequences, max_output_tokens=self.max_tokens, @@ -48,14 +60,22 @@ def try_run(self, prompt_stack: PromptStack) -> TextArtifact: ), ) - return TextArtifact(value=response.text) + usage_metadata = response.usage_metadata - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + return Message( + content=[TextMessageContent(TextArtifact(response.text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage( + input_tokens=usage_metadata.prompt_token_count, output_tokens=usage_metadata.candidates_token_count + ), + ) + + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig - inputs = self._prompt_stack_to_model_input(prompt_stack) - response = self.model_client.generate_content( - inputs, + messages = self._prompt_stack_to_messages(prompt_stack) + response: Iterator[GenerateContentResponse] = self.model_client.generate_content( + messages, stream=True, generation_config=GenerationConfig( stop_sequences=self.tokenizer.stop_sequences, @@ -66,16 +86,27 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: ), ) + prompt_token_count = None for chunk in response: - yield TextArtifact(value=chunk.text) - - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - parts = [prompt_input.content] - - if prompt_input.is_assistant(): - return {"role": "model", "parts": parts} - else: - return {"role": "user", "parts": parts} + usage_metadata = chunk.usage_metadata + + # Only want to output the prompt token count once since it is static each chunk + if prompt_token_count is None: + prompt_token_count = usage_metadata.prompt_token_count + yield DeltaMessage( + content=TextDeltaMessageContent(chunk.text), + role=Message.ASSISTANT_ROLE, + usage=DeltaMessage.Usage( + input_tokens=usage_metadata.prompt_token_count, + output_tokens=usage_metadata.candidates_token_count, + ), + ) + else: + yield DeltaMessage( + content=TextDeltaMessageContent(chunk.text), + role=Message.ASSISTANT_ROLE, + usage=DeltaMessage.Usage(output_tokens=usage_metadata.candidates_token_count), + ) def _default_model_client(self) -> GenerativeModel: genai = import_optional_dependency("google.generativeai") @@ -83,20 +114,35 @@ def _default_model_client(self) -> GenerativeModel: return genai.GenerativeModel(self.model) - def _prompt_stack_to_model_input(self, prompt_stack: PromptStack) -> list[ContentDict]: + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: inputs = [ - self.__to_content_dict(prompt_input) for prompt_input in prompt_stack.inputs if not prompt_input.is_system() + {"role": self.__to_role(message), "parts": self.__to_content(message)} + for message in prompt_stack.messages + if not message.is_system() ] # Gemini does not have the notion of a system message, so we insert it as part of the first message in the history. - system = next((i for i in prompt_stack.inputs if i.is_system()), None) - if system is not None: - inputs[0]["parts"].insert(0, system.content) + system_messages = prompt_stack.system_messages + if system_messages: + inputs[0]["parts"].insert(0, system_messages[0].to_text()) return inputs - def __to_content_dict(self, prompt_input: PromptStack.Input) -> ContentDict: + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> ContentDict | str: ContentDict = import_optional_dependency("google.generativeai.types").ContentDict - message = self._prompt_stack_input_to_message(prompt_input) - return ContentDict(message) + if isinstance(content, TextMessageContent): + return content.artifact.to_text() + elif isinstance(content, ImageMessageContent): + return ContentDict(mime_type=content.artifact.mime_type, data=content.artifact.value) + else: + raise ValueError(f"Unsupported content type: {type(content)}") + + def __to_role(self, message: Message) -> str: + if message.is_assistant(): + return "model" + else: + return "user" + + def __to_content(self, message: Message) -> list[ContentDict | str]: + return [self.__prompt_stack_content_message_content(content) for content in message.content] diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index 3edd252cb..f327010c4 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -5,10 +5,10 @@ from attrs import Factory, define, field -from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer -from griptape.utils import PromptStack, import_optional_dependency +from griptape.common import PromptStack, Message, DeltaMessage, TextDeltaMessageContent +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from huggingface_hub import InferenceClient @@ -47,37 +47,54 @@ class HuggingFaceHubPromptDriver(BasePromptDriver): kw_only=True, ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( prompt, return_full_text=False, max_new_tokens=self.max_tokens, **self.params ) + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + output_tokens = len(self.tokenizer.tokenizer.encode(response)) - return TextArtifact(value=response) + return Message( + content=response, + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( prompt, return_full_text=False, max_new_tokens=self.max_tokens, stream=True, **self.params ) + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + + full_text = "" for token in response: - yield TextArtifact(value=token) + full_text += token + yield DeltaMessage(content=TextDeltaMessageContent(token, index=0)) - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - return {"role": prompt_input.role, "content": prompt_input.content} + output_tokens = len(self.tokenizer.tokenizer.encode(full_text)) + yield DeltaMessage(usage=DeltaMessage.Usage(input_tokens=input_tokens, output_tokens=output_tokens)) def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + messages = [] + for message in prompt_stack.messages: + if len(message.content) == 1: + messages.append({"role": message.role, "content": message.to_text()}) + else: + raise ValueError("Invalid input content length.") + + return messages + def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: - tokens = self.tokenizer.tokenizer.apply_chat_template( - [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], - add_generation_prompt=True, - tokenize=True, - ) + messages = self._prompt_stack_to_messages(prompt_stack) + tokens = self.tokenizer.tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=True) if isinstance(tokens, list): return tokens diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index 4fa291877..6dabc3e20 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -1,13 +1,15 @@ from __future__ import annotations -from collections.abc import Iterator +from collections.abc import Iterator from typing import TYPE_CHECKING + from attrs import Factory, define, field from griptape.artifacts import TextArtifact +from griptape.common import DeltaMessage, PromptStack, Message, TextMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer -from griptape.utils import PromptStack, import_optional_dependency +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from transformers import TextGenerationPipeline @@ -40,43 +42,47 @@ class HuggingFacePipelinePromptDriver(BasePromptDriver): ) ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs] + def try_run(self, prompt_stack: PromptStack) -> Message: + messages = self._prompt_stack_to_messages(prompt_stack) result = self.pipe( - messages, - max_new_tokens=self.max_tokens, - tokenizer=self.tokenizer.tokenizer, - stop_strings=self.tokenizer.stop_sequences, - temperature=self.temperature, - do_sample=True, + messages, max_new_tokens=self.max_tokens, temperature=self.temperature, do_sample=True, **self.params ) if isinstance(result, list): if len(result) == 1: generated_text = result[0]["generated_text"][-1]["content"] - return TextArtifact(value=generated_text) + input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) + output_tokens = len(self.tokenizer.tokenizer.encode(generated_text)) + + return Message( + content=[TextMessageContent(TextArtifact(generated_text))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), + ) else: raise Exception("completion with more than one choice is not supported yet") else: raise Exception("invalid output format") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: raise NotImplementedError("streaming is not supported") def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: return self.tokenizer.tokenizer.decode(self.__prompt_stack_to_tokens(prompt_stack)) - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - return {"role": prompt_input.role, "content": prompt_input.content} + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + messages = [] + + for message in prompt_stack.messages: + messages.append({"role": message.role, "content": message.to_text()}) + + return messages def __prompt_stack_to_tokens(self, prompt_stack: PromptStack) -> list[int]: - tokens = self.tokenizer.tokenizer.apply_chat_template( - [self._prompt_stack_input_to_message(i) for i in prompt_stack.inputs], - add_generation_prompt=True, - tokenize=True, - ) + messages = self._prompt_stack_to_messages(prompt_stack) + tokens = self.tokenizer.tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=True) if isinstance(tokens, list): return tokens diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py index b21176e82..5a78abf29 100644 --- a/griptape/drivers/prompt/ollama_prompt_driver.py +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -5,8 +5,11 @@ from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver from griptape.tokenizers.base_tokenizer import BaseTokenizer -from griptape.utils import PromptStack, import_optional_dependency +from griptape.common import PromptStack, TextMessageContent +from griptape.utils import import_optional_dependency from griptape.tokenizers import SimpleTokenizer +from griptape.common import Message, DeltaMessage, TextDeltaMessageContent +from griptape.common import ImageMessageContent if TYPE_CHECKING: from ollama import Client @@ -46,24 +49,47 @@ class OllamaPromptDriver(BasePromptDriver): kw_only=True, ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: response = self.client.chat(**self._base_params(prompt_stack)) if isinstance(response, dict): - return TextArtifact(value=response["message"]["content"]) + return Message( + content=[TextMessageContent(TextArtifact(value=response["message"]["content"]))], + role=Message.ASSISTANT_ROLE, + ) else: raise Exception("invalid model response") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: stream = self.client.chat(**self._base_params(prompt_stack), stream=True) if isinstance(stream, Iterator): for chunk in stream: - yield TextArtifact(value=chunk["message"]["content"]) + yield DeltaMessage(content=TextDeltaMessageContent(chunk["message"]["content"])) else: raise Exception("invalid model response") def _base_params(self, prompt_stack: PromptStack) -> dict: - messages = [{"role": input.role, "content": input.content} for input in prompt_stack.inputs] + messages = self._prompt_stack_to_messages(prompt_stack) return {"messages": messages, "model": self.model, "options": self.options} + + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + return [ + { + "role": message.role, + "content": message.to_text(), + **( + { + "images": [ + content.artifact.base64 + for content in message.content + if isinstance(content, ImageMessageContent) + ] + } + if any(isinstance(content, ImageMessageContent) for content in message.content) + else {} + ), + } + for message in prompt_stack.messages + ] diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index 9545bd45a..a89b4eb57 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -1,12 +1,28 @@ from __future__ import annotations -from typing import Optional, Literal + from collections.abc import Iterator +from typing import Literal, Optional, TYPE_CHECKING + import openai -from attrs import define, field, Factory +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact -from griptape.utils import PromptStack +from griptape.common import ( + BaseMessageContent, + DeltaMessage, + TextDeltaMessageContent, + ImageMessageContent, + PromptStack, + Message, + TextMessageContent, +) from griptape.drivers import BasePromptDriver -from griptape.tokenizers import OpenAiTokenizer, BaseTokenizer +from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer + + +if TYPE_CHECKING: + from openai.types.chat.chat_completion_message import ChatCompletionMessage + from openai.types.chat.chat_completion_chunk import ChoiceDelta @define @@ -57,57 +73,104 @@ class OpenAiChatPromptDriver(BasePromptDriver): kw_only=True, ) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: result = self.client.chat.completions.create(**self._base_params(prompt_stack)) if len(result.choices) == 1: - return TextArtifact(value=result.choices[0].message.content.strip()) + message = result.choices[0].message + + return Message( + content=[self.__message_to_prompt_stack_content(message)], + role=message.role, + usage=Message.Usage( + input_tokens=result.usage.prompt_tokens, output_tokens=result.usage.completion_tokens + ), + ) else: raise Exception("Completion with more than one choice is not supported yet.") - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: result = self.client.chat.completions.create(**self._base_params(prompt_stack), stream=True) for chunk in result: - if len(chunk.choices) == 1: - delta = chunk.choices[0].delta - else: - raise Exception("Completion with more than one choice is not supported yet.") - - if delta.content is not None: - delta_content = delta.content - - yield TextArtifact(value=delta_content) - - def _prompt_stack_input_to_message(self, prompt_input: PromptStack.Input) -> dict: - content = prompt_input.content - - if prompt_input.is_system(): - return {"role": "system", "content": content} - elif prompt_input.is_assistant(): - return {"role": "assistant", "content": content} - else: - return {"role": "user", "content": content} + if chunk.usage is not None: + yield DeltaMessage( + usage=DeltaMessage.Usage( + input_tokens=chunk.usage.prompt_tokens, output_tokens=chunk.usage.completion_tokens + ) + ) + elif chunk.choices is not None: + if len(chunk.choices) == 1: + choice = chunk.choices[0] + delta = choice.delta + + yield DeltaMessage(content=self.__message_delta_to_prompt_stack_content_delta(delta)) + else: + raise Exception("Completion with more than one choice is not supported yet.") + + def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + return [ + {"role": self.__to_role(message), "content": self.__to_content(message)} + for message in prompt_stack.messages + ] def _base_params(self, prompt_stack: PromptStack) -> dict: params = { "model": self.model, "temperature": self.temperature, - "stop": self.tokenizer.stop_sequences, "user": self.user, "seed": self.seed, + **({"stop": self.tokenizer.stop_sequences} if self.tokenizer.stop_sequences else {}), + **({"max_tokens": self.max_tokens} if self.max_tokens is not None else {}), + **({"stream_options": {"include_usage": True}} if self.stream else {}), } if self.response_format == "json_object": params["response_format"] = {"type": "json_object"} - # JSON mode still requires a system input instructing the LLM to output JSON. - prompt_stack.add_system_input("Provide your response as a valid JSON object.") + # JSON mode still requires a system message instructing the LLM to output JSON. + prompt_stack.add_system_message("Provide your response as a valid JSON object.") - messages = [self._prompt_stack_input_to_message(input) for input in prompt_stack.inputs] - - if self.max_tokens is not None: - params["max_tokens"] = self.max_tokens + messages = self._prompt_stack_to_messages(prompt_stack) params["messages"] = messages return params + + def __to_role(self, message: Message) -> str: + if message.is_system(): + return "system" + elif message.is_assistant(): + return "assistant" + else: + return "user" + + def __to_content(self, message: Message) -> str | list[dict]: + if all(isinstance(content, TextMessageContent) for content in message.content): + return message.to_text() + else: + return [self.__prompt_stack_content_message_content(content) for content in message.content] + + def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + if isinstance(content, TextMessageContent): + return {"type": "text", "text": content.artifact.to_text()} + elif isinstance(content, ImageMessageContent): + return { + "type": "image_url", + "image_url": {"url": f"data:{content.artifact.mime_type};base64,{content.artifact.base64}"}, + } + else: + raise ValueError(f"Unsupported content type: {type(content)}") + + def __message_to_prompt_stack_content(self, message: ChatCompletionMessage) -> BaseMessageContent: + if message.content is not None: + return TextMessageContent(TextArtifact(message.content)) + else: + raise ValueError(f"Unsupported message type: {message}") + + def __message_delta_to_prompt_stack_content_delta(self, content_delta: ChoiceDelta) -> TextDeltaMessageContent: + if content_delta.content is None: + return TextDeltaMessageContent("") + else: + delta_content = content_delta.content + + return TextDeltaMessageContent(delta_content) diff --git a/griptape/drivers/rerank/__init__.py b/griptape/drivers/rerank/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/drivers/rerank/base_rerank_driver.py b/griptape/drivers/rerank/base_rerank_driver.py new file mode 100644 index 000000000..975575d49 --- /dev/null +++ b/griptape/drivers/rerank/base_rerank_driver.py @@ -0,0 +1,9 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.artifacts import TextArtifact + + +@define(kw_only=True) +class BaseRerankDriver(ABC): + @abstractmethod + def run(self, query: str, artifacts: list[TextArtifact]) -> list[TextArtifact]: ... diff --git a/griptape/drivers/rerank/cohere_rerank_driver.py b/griptape/drivers/rerank/cohere_rerank_driver.py new file mode 100644 index 000000000..57a7863d4 --- /dev/null +++ b/griptape/drivers/rerank/cohere_rerank_driver.py @@ -0,0 +1,32 @@ +from __future__ import annotations +from typing import TYPE_CHECKING, Optional +from attrs import define, field, Factory +from griptape.artifacts import TextArtifact +from griptape.drivers import BaseRerankDriver +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from cohere import Client + + +@define(kw_only=True) +class CohereRerankDriver(BaseRerankDriver): + model: str = field(default="rerank-english-v3.0", metadata={"serializable": True}) + top_n: Optional[int] = field(default=None) + + api_key: str = field(metadata={"serializable": True}) + client: Client = field( + default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True) + ) + + def run(self, query: str, artifacts: list[TextArtifact]) -> list[TextArtifact]: + artifacts_dict = {str(hash(a.value)): a for a in artifacts} + response = self.client.rerank( + model=self.model, + query=query, + documents=[a.value for a in artifacts_dict.values()], + return_documents=True, + top_n=self.top_n, + ) + + return [artifacts_dict[str(hash(r.document.text))] for r in response.results] diff --git a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py index 2e9968b63..e29a7fa70 100644 --- a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py +++ b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py @@ -16,7 +16,7 @@ def query( include_vectors: bool = False, offset: Optional[int] = None, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Queries the MongoDB collection for documents that match the provided query string. Results can be customized based on parameters like count, namespace, inclusion of vectors, offset, and index. @@ -50,7 +50,7 @@ def query( pipeline.append({"$project": {"similarityScore": {"$meta": "searchScore"}, "document": "$$ROOT"}}) return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=str(doc["_id"]), vector=doc[self.vector_path] if include_vectors else [], score=doc["similarityScore"], diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 55a758da1..2957d7557 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -1,65 +1,83 @@ from __future__ import annotations +import uuid from abc import ABC, abstractmethod from concurrent import futures from dataclasses import dataclass -from attrs import define, field, Factory +from typing import Any, Callable from typing import Optional +from attrs import define, field, Factory from griptape import utils -from griptape.mixins import SerializableMixin -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact from griptape.drivers import BaseEmbeddingDriver +from griptape.mixins import SerializableMixin @define class BaseVectorStoreDriver(SerializableMixin, ABC): DEFAULT_QUERY_COUNT = 5 - @dataclass - class QueryResult: - id: str - vector: Optional[list[float]] - score: float - meta: Optional[dict] = None - namespace: Optional[str] = None - @dataclass class Entry: id: str - vector: list[float] + vector: Optional[list[float]] = None + score: Optional[float] = None meta: Optional[dict] = None namespace: Optional[str] = None + @staticmethod + def from_dict(data: dict[str, Any]) -> BaseVectorStoreDriver.Entry: + return BaseVectorStoreDriver.Entry(**data) + + def to_artifact(self) -> BaseArtifact: + return BaseArtifact.from_json(self.meta["artifact"]) # pyright: ignore[reportOptionalSubscript] + embedding_driver: BaseEmbeddingDriver = field(kw_only=True, metadata={"serializable": True}) - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) def upsert_text_artifacts( - self, artifacts: dict[str, list[TextArtifact]], meta: Optional[dict] = None, **kwargs + self, artifacts: list[TextArtifact] | dict[str, list[TextArtifact]], meta: Optional[dict] = None, **kwargs ) -> None: - utils.execute_futures_dict( - { - namespace: self.futures_executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) - for namespace, artifact_list in artifacts.items() - for a in artifact_list - } - ) + with self.futures_executor_fn() as executor: + if isinstance(artifacts, list): + utils.execute_futures_list( + [executor.submit(self.upsert_text_artifact, a, None, meta, **kwargs) for a in artifacts] + ) + else: + utils.execute_futures_dict( + { + namespace: executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) + for namespace, artifact_list in artifacts.items() + for a in artifact_list + } + ) def upsert_text_artifact( - self, artifact: TextArtifact, namespace: Optional[str] = None, meta: Optional[dict] = None, **kwargs + self, + artifact: TextArtifact, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + vector_id: Optional[str] = None, + **kwargs, ) -> str: - if not meta: - meta = {} + meta = {} if meta is None else meta - meta["artifact"] = artifact.to_json() + if vector_id is None: + value = artifact.to_text() if artifact.reference is None else artifact.to_text() + str(artifact.reference) + vector_id = self._get_default_vector_id(value) - if artifact.embedding: - vector = artifact.embedding + if self.does_entry_exist(vector_id, namespace): + return vector_id else: - vector = artifact.generate_embedding(self.embedding_driver) + meta["artifact"] = artifact.to_json() - if isinstance(vector, list): - return self.upsert_vector(vector, vector_id=artifact.id, namespace=namespace, meta=meta, **kwargs) - else: - raise ValueError("Vector must be an instance of 'list'.") + vector = artifact.embedding if artifact.embedding else artifact.generate_embedding(self.embedding_driver) + + if isinstance(vector, list): + return self.upsert_vector(vector, vector_id=vector_id, namespace=namespace, meta=meta, **kwargs) + else: + raise ValueError("Vector must be an instance of 'list'.") def upsert_text( self, @@ -69,13 +87,30 @@ def upsert_text( meta: Optional[dict] = None, **kwargs, ) -> str: - return self.upsert_vector( - self.embedding_driver.embed_string(string), - vector_id=vector_id, - namespace=namespace, - meta=meta if meta else {}, - **kwargs, - ) + vector_id = self._get_default_vector_id(string) if vector_id is None else vector_id + + if self.does_entry_exist(vector_id, namespace): + return vector_id + else: + return self.upsert_vector( + self.embedding_driver.embed_string(string), + vector_id=vector_id, + namespace=namespace, + meta=meta if meta else {}, + **kwargs, + ) + + def does_entry_exist(self, vector_id: str, namespace: Optional[str] = None) -> bool: + try: + return self.load_entry(vector_id, namespace) is not None + except Exception: + return False + + def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: + result = self.load_entries(namespace) + artifacts = [r.to_artifact() for r in result] + + return ListArtifact([a for a in artifacts if isinstance(a, TextArtifact)]) @abstractmethod def delete_vector(self, vector_id: str) -> None: ... @@ -104,4 +139,7 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[QueryResult]: ... + ) -> list[Entry]: ... + + def _get_default_vector_id(self, value: str) -> str: + return str(uuid.uuid5(uuid.NAMESPACE_OID, value)) diff --git a/griptape/drivers/vector/dummy_vector_store_driver.py b/griptape/drivers/vector/dummy_vector_store_driver.py index f53a5eb90..04dea2181 100644 --- a/griptape/drivers/vector/dummy_vector_store_driver.py +++ b/griptape/drivers/vector/dummy_vector_store_driver.py @@ -36,5 +36,5 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: raise DummyException(__class__.__name__, "query") diff --git a/griptape/drivers/vector/local_vector_store_driver.py b/griptape/drivers/vector/local_vector_store_driver.py index 4b9dae00f..1a86225c6 100644 --- a/griptape/drivers/vector/local_vector_store_driver.py +++ b/griptape/drivers/vector/local_vector_store_driver.py @@ -1,15 +1,49 @@ -from typing import Optional, Callable +import json +import os +import threading +from dataclasses import asdict +from typing import Optional, Callable, TextIO +from attrs import define, field, Factory from numpy import dot from numpy.linalg import norm from griptape import utils from griptape.drivers import BaseVectorStoreDriver -from attrs import define, field -@define +@define(kw_only=True) class LocalVectorStoreDriver(BaseVectorStoreDriver): - entries: dict[str, BaseVectorStoreDriver.Entry] = field(factory=dict, kw_only=True) - relatedness_fn: Callable = field(default=lambda x, y: dot(x, y) / (norm(x) * norm(y)), kw_only=True) + entries: dict[str, BaseVectorStoreDriver.Entry] = field(factory=dict) + persist_file: Optional[str] = field(default=None) + relatedness_fn: Callable = field(default=lambda x, y: dot(x, y) / (norm(x) * norm(y))) + thread_lock: threading.Lock = field(default=Factory(lambda: threading.Lock())) + + def __attrs_post_init__(self) -> None: + if self.persist_file is not None: + directory = os.path.dirname(self.persist_file) + + if directory and not os.path.exists(directory): + os.makedirs(directory) + + if not os.path.isfile(self.persist_file): + with open(self.persist_file, "w") as file: + self.save_entries_to_file(file) + + with open(self.persist_file, "r+") as file: + if os.path.getsize(self.persist_file) > 0: + self.entries = self.load_entries_from_file(file) + else: + self.save_entries_to_file(file) + + def save_entries_to_file(self, json_file: TextIO) -> None: + with self.thread_lock: + serialized_data = {k: asdict(v) for k, v in self.entries.items()} + + json.dump(serialized_data, json_file) + + def load_entries_from_file(self, json_file: TextIO) -> dict[str, BaseVectorStoreDriver.Entry]: + data = json.load(json_file) + + return {k: BaseVectorStoreDriver.Entry.from_dict(v) for k, v in data.items()} def upsert_vector( self, @@ -21,9 +55,16 @@ def upsert_vector( ) -> str: vector_id = vector_id if vector_id else utils.str_to_hash(str(vector)) - self.entries[self._namespaced_vector_id(vector_id, namespace)] = self.Entry( - id=vector_id, vector=vector, meta=meta, namespace=namespace - ) + with self.thread_lock: + self.entries[self._namespaced_vector_id(vector_id, namespace)] = self.Entry( + id=vector_id, vector=vector, meta=meta, namespace=namespace + ) + + if self.persist_file is not None: + # TODO: optimize later since it reserializes all entries from memory and stores them in the JSON file + # every time a new vector is inserted + with open(self.persist_file, "w") as file: + self.save_entries_to_file(file) return vector_id @@ -40,7 +81,7 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: query_embedding = self.embedding_driver.embed_string(query) if namespace: @@ -54,7 +95,7 @@ def query( entries_and_relatednesses.sort(key=lambda x: x[1], reverse=True) result = [ - BaseVectorStoreDriver.QueryResult(id=er[0].id, vector=er[0].vector, score=er[1], meta=er[0].meta) + BaseVectorStoreDriver.Entry(id=er[0].id, vector=er[0].vector, score=er[1], meta=er[0].meta) for er in entries_and_relatednesses ][:count] @@ -62,12 +103,12 @@ def query( return result else: return [ - BaseVectorStoreDriver.QueryResult(id=r.id, vector=[], score=r.score, meta=r.meta, namespace=r.namespace) + BaseVectorStoreDriver.Entry(id=r.id, vector=[], score=r.score, meta=r.meta, namespace=r.namespace) for r in result ] - def _namespaced_vector_id(self, vector_id: str, namespace: Optional[str]): - return vector_id if namespace is None else f"{namespace}-{vector_id}" - def delete_vector(self, vector_id: str): raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") + + def _namespaced_vector_id(self, vector_id: str, namespace: Optional[str]): + return vector_id if namespace is None else f"{namespace}-{vector_id}" diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index cccc716f8..f20530cff 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -1,5 +1,6 @@ from __future__ import annotations from typing import Optional, Any, TYPE_CHECKING +from griptape import utils from griptape.utils import import_optional_dependency from griptape.drivers import BaseVectorStoreDriver from griptape.artifacts import TextArtifact @@ -65,7 +66,12 @@ def upsert_text( raise ValueError(f"Failed to upsert text: {response}") def upsert_text_artifact( - self, artifact: TextArtifact, namespace: Optional[str] = None, meta: Optional[dict] = None, **kwargs + self, + artifact: TextArtifact, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + vector_id: Optional[str] = None, + **kwargs, ) -> str: """Upsert a text artifact into the Marqo index. @@ -73,15 +79,17 @@ def upsert_text_artifact( artifact: The text artifact to be indexed. namespace: An optional namespace for the artifact. meta: An optional dictionary of metadata for the artifact. + vector_id: An optional explicit vector_id. Returns: str: The ID of the artifact that was added. """ artifact_json = artifact.to_json() + vector_id = utils.str_to_hash(artifact.value) if vector_id is None else vector_id doc = { - "_id": artifact.id, + "_id": vector_id, "Description": artifact.value, # Description will be treated as tensor field "artifact": str(artifact_json), "namespace": namespace, @@ -160,7 +168,7 @@ def query( include_vectors: bool = False, include_metadata: bool = True, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Query the Marqo index for documents. Args: @@ -188,7 +196,7 @@ def query( ] return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=r["_id"], vector=r["_tensor_facets"][0]["_embedding"] if include_vectors else [], score=r["_score"], diff --git a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py index c5368de3d..e60524714 100644 --- a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py +++ b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py @@ -90,10 +90,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD Entries can optionally be filtered by namespace. """ collection = self.get_collection() - if namespace is None: - cursor = collection.find() - else: - cursor = collection.find({"namespace": namespace}) + cursor = collection.find() if namespace is None else collection.find({"namespace": namespace}) return [ BaseVectorStoreDriver.Entry( @@ -110,7 +107,7 @@ def query( include_vectors: bool = False, offset: Optional[int] = None, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Queries the MongoDB collection for documents that match the provided query string. Results can be customized based on parameters like count, namespace, inclusion of vectors, offset, and index. @@ -148,7 +145,7 @@ def query( pipeline[0]["$vectorSearch"]["filter"] = {"namespace": namespace} results = [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=str(doc["_id"]), vector=doc[self.vector_path] if include_vectors else [], score=doc["score"], diff --git a/griptape/drivers/vector/opensearch_vector_store_driver.py b/griptape/drivers/vector/opensearch_vector_store_driver.py index 7ff00d2de..81add74aa 100644 --- a/griptape/drivers/vector/opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/opensearch_vector_store_driver.py @@ -127,13 +127,13 @@ def query( include_metadata=True, field_name: str = "vector", **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Performs a nearest neighbor search on OpenSearch to find vectors similar to the provided query string. Results can be limited using the count parameter and optionally filtered by a namespace. Returns: - A list of BaseVectorStoreDriver.QueryResult objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. + A list of BaseVectorStoreDriver.Entry objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. """ count = count if count else BaseVectorStoreDriver.DEFAULT_QUERY_COUNT vector = self.embedding_driver.embed_string(query) @@ -150,7 +150,7 @@ def query( response = self.client.search(index=self.index_name, body=query_body) return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=hit["_id"], namespace=hit["_source"].get("namespace") if namespace else None, score=hit["_score"], diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index 8058c8774..29c657589 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -127,7 +127,7 @@ def query( include_vectors: bool = False, distance_metric: str = "cosine_distance", **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Performs a search on the collection to find vectors similar to the provided input vector, optionally filtering to only those that match the provided namespace. """ @@ -163,7 +163,7 @@ def query( results = query_result.limit(count).all() return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=str(result[0].id), vector=result[0].vector if include_vectors else None, score=result[1], diff --git a/griptape/drivers/vector/pinecone_vector_store_driver.py b/griptape/drivers/vector/pinecone_vector_store_driver.py index daf378087..6da2f2418 100644 --- a/griptape/drivers/vector/pinecone_vector_store_driver.py +++ b/griptape/drivers/vector/pinecone_vector_store_driver.py @@ -77,7 +77,7 @@ def query( # PineconeVectorStorageDriver-specific params: include_metadata=True, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: vector = self.embedding_driver.embed_string(query) params = { @@ -90,7 +90,7 @@ def query( results = self.index.query(vector=vector, **params) return [ - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=r["id"], vector=r["values"], score=r["score"], meta=r["metadata"], namespace=results["namespace"] ) for r in results["matches"] diff --git a/griptape/drivers/vector/qdrant_vector_store_driver.py b/griptape/drivers/vector/qdrant_vector_store_driver.py new file mode 100644 index 000000000..5159bdb0a --- /dev/null +++ b/griptape/drivers/vector/qdrant_vector_store_driver.py @@ -0,0 +1,207 @@ +from __future__ import annotations +from typing import Optional +from attrs import define, field +from griptape.drivers import BaseVectorStoreDriver +from griptape.utils import import_optional_dependency +import uuid +import logging + +DEFAULT_DISTANCE = "Cosine" +CONTENT_PAYLOAD_KEY = "data" + + +@define +class QdrantVectorStoreDriver(BaseVectorStoreDriver): + """ + Attributes: + location: An optional location for the Qdrant client. If set to ':memory:', an in-memory client is used. + url: An optional Qdrant API URL. + host: An optional Qdrant host. + path: Persistence path for QdrantLocal. Default: None + port: The port number for the Qdrant client. Defaults: 6333. + grpc_port: The gRPC port number for the Qdrant client. Defaults: 6334. + prefer_grpc: A boolean indicating whether to prefer gRPC over HTTP. Defaults: False. + force_disable_check_same_thread: For QdrantLocal, force disable check_same_thread. Default: False Only use this if you can guarantee that you can resolve the thread safety outside QdrantClient. + timeout: Timeout for REST and gRPC API requests. Default: 5 seconds for REST and unlimited for gRPC + api_key: API key for authentication in Qdrant Cloud. Defaults: False + https: If true - use HTTPS(SSL) protocol. Default: None + prefix: Add prefix to the REST URL path. Example: service/v1 will result in Example: service/v1 will result in http://localhost:6333/service/v1/{qdrant-endpoint} for REST API. Defaults: None + distance: The distance metric to be used for the vectors. Defaults: 'COSINE'. + collection_name: The name of the Qdrant collection. + vector_name: An optional name for the vectors. + content_payload_key: The key for the content payload in the metadata. Defaults: 'data'. + """ + + location: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + url: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + host: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + path: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + port: int = field(default=6333, kw_only=True, metadata={"serializable": True}) + grpc_port: int = field(default=6334, kw_only=True, metadata={"serializable": True}) + prefer_grpc: bool = field(default=False, kw_only=True, metadata={"serializable": True}) + api_key: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + https: bool = field(default=None, kw_only=True, metadata={"serializable": True}) + prefix: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + force_disable_check_same_thread: Optional[bool] = field( + default=False, kw_only=True, metadata={"serializable": True} + ) + timeout: Optional[int] = field(default=5, kw_only=True, metadata={"serializable": True}) + distance: str = field(default=DEFAULT_DISTANCE, kw_only=True, metadata={"serializable": True}) + collection_name: str = field(kw_only=True, metadata={"serializable": True}) + vector_name: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + content_payload_key: str = field(default=CONTENT_PAYLOAD_KEY, kw_only=True, metadata={"serializable": True}) + + def __attrs_post_init__(self) -> None: + self.client = import_optional_dependency("qdrant_client").QdrantClient( + location=self.location, + url=self.url, + host=self.host, + path=self.path, + port=self.port, + prefer_grpc=self.prefer_grpc, + grpc_port=self.grpc_port, + api_key=self.api_key, + https=self.https, + prefix=self.prefix, + force_disable_check_same_thread=self.force_disable_check_same_thread, + timeout=self.timeout, + ) + + def delete_vector(self, vector_id: str) -> None: + """ + Delete a vector from the Qdrant collection based on its ID. + + Parameters: + vector_id (str | id): ID of the vector to delete. + """ + deletion_response = self.client.delete( + collection_name=self.collection_name, + points_selector=import_optional_dependency("qdrant_client.http.models").PointIdsList(points=[vector_id]), + ) + if deletion_response.status == import_optional_dependency("qdrant_client.http.models").UpdateStatus.COMPLETED: + logging.info(f"ID {vector_id} is successfully deleted") + + def query( + self, + query: str, + count: Optional[int] = None, + namespace: Optional[str] = None, + include_vectors: bool = False, + **kwargs, + ) -> list[BaseVectorStoreDriver.Entry]: + """ + Query the Qdrant collection based on a query vector. + + Parameters: + query (str): Query string. + count (Optional[int]): Optional number of results to return. + namespace (Optional[str]): Optional namespace of the vectors. + include_vectors (bool): Whether to include vectors in the results. + + Returns: + list[BaseVectorStoreDriver.Entry]: List of Entry objects. + """ + query_vector = self.embedding_driver.embed_string(query) + + # Create a search request + results = self.client.search(collection_name=self.collection_name, query_vector=query_vector, limit=count) + + # Convert results to QueryResult objects + query_results = [ + BaseVectorStoreDriver.Entry( + id=result.id, + vector=result.vector if include_vectors else [], + score=result.score, + meta={k: v for k, v in result.payload.items() if k not in ["_score", "_tensor_facets"]}, + ) + for result in results + ] + return query_results + + def upsert_vector( + self, + vector: list[float], + vector_id: Optional[str] = None, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + content: Optional[str] = None, + **kwargs, + ) -> str: + """ + Upsert vectors into the Qdrant collection. + + Parameters: + vector (list[float]): The vector to be upserted. + vector_id (Optional[str]): Optional vector ID. + namespace (Optional[str]): Optional namespace for the vector. + meta (Optional[dict]): Optional dictionary containing metadata. + content (Optional[str]): The text content to be included in the payload. + + Returns: + str: The ID of the upserted vector. + """ + + if vector_id is None: + vector_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, str(vector))) + + if meta is None: + meta = {} + + if content: + meta[self.content_payload_key] = content + + points = import_optional_dependency("qdrant_client.http.models").Batch( + ids=[vector_id], vectors=[vector], payloads=[meta] if meta else None + ) + + self.client.upsert(collection_name=self.collection_name, points=points) + return vector_id + + def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + """ + Load a vector entry from the Qdrant collection based on its ID. + + Parameters: + vector_id (str): ID of the vector to load. + namespace (str, optional): Optional namespace of the vector. + + Returns: + Optional[BaseVectorStoreDriver.Entry]: Vector entry if found, else None. + """ + results = self.client.retrieve(collection_name=self.collection_name, ids=[vector_id]) + if results: + entry = results[0] + return BaseVectorStoreDriver.Entry( + id=entry.id, + vector=entry.vector, + meta={k: v for k, v in entry.payload.items() if k not in ["_score", "_tensor_facets"]}, + ) + else: + return None + + def load_entries(self, namespace: Optional[str] = None, **kwargs) -> list[BaseVectorStoreDriver.Entry]: + """ + Load vector entries from the Qdrant collection. + + Parameters: + namespace: Optional namespace of the vectors. + + Returns: + List of points. + """ + + results = self.client.retrieve( + collection_name=self.collection_name, + ids=kwargs.get("ids", []), + with_payload=kwargs.get("with_payload", True), + with_vectors=kwargs.get("with_vectors", True), + ) + + return [ + BaseVectorStoreDriver.Entry( + id=entry.id, + vector=entry.vector if kwargs.get("with_vectors", True) else [], + meta={k: v for k, v in entry.payload.items() if k not in ["_score", "_tensor_facets"]}, + ) + for entry in results + ] diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index 6e39775b7..e58e4b3ea 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -1,14 +1,11 @@ from __future__ import annotations import json -import logging import numpy as np from griptape.utils import import_optional_dependency, str_to_hash from typing import Optional, TYPE_CHECKING from attrs import define, field, Factory from griptape.drivers import BaseVectorStoreDriver -logging.basicConfig(level=logging.WARNING) - if TYPE_CHECKING: from redis import Redis @@ -111,13 +108,13 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Performs a nearest neighbor search on Redis to find vectors similar to the provided input vector. Results can be limited using the count parameter and optionally filtered by a namespace. Returns: - A list of BaseVectorStoreDriver.QueryResult objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. + A list of BaseVectorStoreDriver.Entry objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. """ Query = import_optional_dependency("redis.commands.search.query").Query @@ -143,7 +140,7 @@ def query( vector_id = document.id.split(":")[1] if ":" in document.id else document.id vector_float_list = json.loads(document.vec_string) if include_vectors else None query_results.append( - BaseVectorStoreDriver.QueryResult( + BaseVectorStoreDriver.Entry( id=vector_id, vector=vector_float_list, score=float(document.score), diff --git a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py index eb33aeb19..28f225ba8 100644 --- a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py @@ -48,51 +48,50 @@ def convert_a(self, el, text, convert_as_inline): return super().convert_a(el, text, convert_as_inline) return text - with sync_playwright() as p: - with p.chromium.launch(headless=True) as browser: - page = browser.new_page() + with sync_playwright() as p, p.chromium.launch(headless=True) as browser: + page = browser.new_page() - def skip_loading_images(route): - if route.request.resource_type == "image": - return route.abort() - route.continue_() + def skip_loading_images(route): + if route.request.resource_type == "image": + return route.abort() + route.continue_() - page.route("**/*", skip_loading_images) + page.route("**/*", skip_loading_images) - page.goto(url) + page.goto(url) - # Some websites require a delay before the content is fully loaded - # even after the browser has emitted "load" event. - if self.timeout: - page.wait_for_timeout(self.timeout) + # Some websites require a delay before the content is fully loaded + # even after the browser has emitted "load" event. + if self.timeout: + page.wait_for_timeout(self.timeout) - content = page.content() + content = page.content() - if not content: - raise Exception("can't access URL") + if not content: + raise Exception("can't access URL") - soup = BeautifulSoup(content, "html.parser") + soup = BeautifulSoup(content, "html.parser") - # Remove unwanted elements - exclude_selector = ",".join( - self.exclude_tags + [f".{c}" for c in self.exclude_classes] + [f"#{i}" for i in self.exclude_ids] - ) - if exclude_selector: - for s in soup.select(exclude_selector): - s.extract() + # Remove unwanted elements + exclude_selector = ",".join( + self.exclude_tags + [f".{c}" for c in self.exclude_classes] + [f"#{i}" for i in self.exclude_ids] + ) + if exclude_selector: + for s in soup.select(exclude_selector): + s.extract() - text = OptionalLinksMarkdownConverter().convert_soup(soup) + text = OptionalLinksMarkdownConverter().convert_soup(soup) - # Remove leading and trailing whitespace from the entire text - text = text.strip() + # Remove leading and trailing whitespace from the entire text + text = text.strip() - # Remove trailing whitespace from each line - text = re.sub(r"[ \t]+$", "", text, flags=re.MULTILINE) + # Remove trailing whitespace from each line + text = re.sub(r"[ \t]+$", "", text, flags=re.MULTILINE) - # Indent using 2 spaces instead of tabs - text = re.sub(r"(\n?\s*?)\t", r"\1 ", text) + # Indent using 2 spaces instead of tabs + text = re.sub(r"(\n?\s*?)\t", r"\1 ", text) - # Remove triple+ newlines (keep double newlines for paragraphs) - text = re.sub(r"\n\n+", "\n\n", text) + # Remove triple+ newlines (keep double newlines for paragraphs) + text = re.sub(r"\n\n+", "\n\n", text) - return TextArtifact(text) + return TextArtifact(text) diff --git a/griptape/drivers/web_scraper/proxy_web_scraper_driver.py b/griptape/drivers/web_scraper/proxy_web_scraper_driver.py new file mode 100644 index 000000000..4a9213365 --- /dev/null +++ b/griptape/drivers/web_scraper/proxy_web_scraper_driver.py @@ -0,0 +1,17 @@ +from __future__ import annotations + +from attrs import field, Factory, define +import requests + +from griptape.artifacts import TextArtifact +from griptape.drivers import BaseWebScraperDriver + + +@define +class ProxyWebScraperDriver(BaseWebScraperDriver): + proxies: dict = field(kw_only=True, metadata={"serializable": False}) + params: dict = field(default=Factory(dict), kw_only=True, metadata={"serializable": True}) + + def scrape_url(self, url: str) -> TextArtifact: + response = requests.get(url, proxies=self.proxies, **self.params) + return TextArtifact(response.text) diff --git a/griptape/drivers/web_search/__init__.py b/griptape/drivers/web_search/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/drivers/web_search/base_web_search_driver.py b/griptape/drivers/web_search/base_web_search_driver.py new file mode 100644 index 000000000..2b5662155 --- /dev/null +++ b/griptape/drivers/web_search/base_web_search_driver.py @@ -0,0 +1,14 @@ +from abc import ABC, abstractmethod +from attrs import field, define + +from griptape.artifacts import ListArtifact + + +@define +class BaseWebSearchDriver(ABC): + results_count: int = field(default=5, kw_only=True) + language: str = field(default="en", kw_only=True) + country: str = field(default="us", kw_only=True) + + @abstractmethod + def search(self, query: str, **kwargs) -> ListArtifact: ... diff --git a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py new file mode 100644 index 000000000..ade6ed85c --- /dev/null +++ b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py @@ -0,0 +1,29 @@ +from __future__ import annotations +import json +from typing import TYPE_CHECKING +from attrs import define, field, Factory +from griptape.artifacts import TextArtifact, ListArtifact +from griptape.drivers import BaseWebSearchDriver +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from duckduckgo_search import DDGS + + +@define +class DuckDuckGoWebSearchDriver(BaseWebSearchDriver): + client: DDGS = field(default=Factory(lambda: import_optional_dependency("duckduckgo_search").DDGS()), kw_only=True) + + def search(self, query: str, **kwargs) -> ListArtifact: + try: + results = self.client.text(query, region=f"{self.language}-{self.country}", max_results=self.results_count) + return ListArtifact( + [ + TextArtifact( + json.dumps({"title": result["title"], "url": result["href"], "description": result["body"]}) + ) + for result in results + ] + ) + except Exception as e: + raise Exception(f"Error searching '{query}' with DuckDuckGo: {e}") from e diff --git a/griptape/drivers/web_search/google_web_search_driver.py b/griptape/drivers/web_search/google_web_search_driver.py new file mode 100644 index 000000000..631170532 --- /dev/null +++ b/griptape/drivers/web_search/google_web_search_driver.py @@ -0,0 +1,39 @@ +from attrs import define, field +from griptape.artifacts import TextArtifact, ListArtifact +from griptape.drivers import BaseWebSearchDriver +import requests +import json + + +@define +class GoogleWebSearchDriver(BaseWebSearchDriver): + api_key: str = field(default=None, kw_only=True) + search_id: str = field(default=None, kw_only=True) + + def search(self, query: str, **kwargs) -> ListArtifact: + return ListArtifact([TextArtifact(json.dumps(result)) for result in self._search_google(query, **kwargs)]) + + def _search_google(self, query: str, **kwargs) -> list[dict]: + url = ( + f"https://www.googleapis.com/customsearch/v1?" + f"key={self.api_key}&" + f"cx={self.search_id}&" + f"q={query}&" + f"start=0&" + f"lr=lang_{self.language}&" + f"num={self.results_count}&" + f"gl={self.country}" + ) + response = requests.get(url) + + if response.status_code == 200: + data = response.json() + + links = [{"url": r["link"], "title": r["title"], "description": r["snippet"]} for r in data["items"]] + + return links + else: + raise Exception( + f"Google Search API returned an error with status code " + f"{response.status_code} and reason '{response.reason}'" + ) diff --git a/griptape/engines/__init__.py b/griptape/engines/__init__.py index 17adaa53d..7835b2238 100644 --- a/griptape/engines/__init__.py +++ b/griptape/engines/__init__.py @@ -1,8 +1,6 @@ from .extraction.base_extraction_engine import BaseExtractionEngine from .extraction.csv_extraction_engine import CsvExtractionEngine from .extraction.json_extraction_engine import JsonExtractionEngine -from .query.base_query_engine import BaseQueryEngine -from .query.vector_query_engine import VectorQueryEngine from .summary.base_summary_engine import BaseSummaryEngine from .summary.prompt_summary_engine import PromptSummaryEngine from .image.base_image_generation_engine import BaseImageGenerationEngine @@ -15,8 +13,6 @@ from .audio.audio_transcription_engine import AudioTranscriptionEngine __all__ = [ - "BaseQueryEngine", - "VectorQueryEngine", "BaseSummaryEngine", "PromptSummaryEngine", "BaseExtractionEngine", diff --git a/griptape/engines/extraction/csv_extraction_engine.py b/griptape/engines/extraction/csv_extraction_engine.py index fe4d0e6c7..6fe9bb879 100644 --- a/griptape/engines/extraction/csv_extraction_engine.py +++ b/griptape/engines/extraction/csv_extraction_engine.py @@ -4,7 +4,8 @@ import io from attrs import field, Factory, define from griptape.artifacts import TextArtifact, CsvRowArtifact, ListArtifact, ErrorArtifact -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.common.prompt_stack.messages.message import Message from griptape.engines import BaseExtractionEngine from griptape.utils import J2 from griptape.rules import Ruleset @@ -63,9 +64,7 @@ def _extract_rec( if self.prompt_driver.tokenizer.count_input_tokens_left(full_text) >= self.min_response_tokens: rows.extend( self.text_to_csv_rows( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(full_text, role=PromptStack.USER_ROLE)]) - ).value, + self.prompt_driver.run(PromptStack(messages=[Message(full_text, role=Message.USER_ROLE)])).value, column_names, ) ) @@ -81,9 +80,7 @@ def _extract_rec( rows.extend( self.text_to_csv_rows( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(partial_text, role=PromptStack.USER_ROLE)]) - ).value, + self.prompt_driver.run(PromptStack(messages=[Message(partial_text, role=Message.USER_ROLE)])).value, column_names, ) ) diff --git a/griptape/engines/extraction/json_extraction_engine.py b/griptape/engines/extraction/json_extraction_engine.py index 05db19d40..830092dab 100644 --- a/griptape/engines/extraction/json_extraction_engine.py +++ b/griptape/engines/extraction/json_extraction_engine.py @@ -3,9 +3,10 @@ import json from attrs import field, Factory, define from griptape.artifacts import TextArtifact, ListArtifact, ErrorArtifact +from griptape.common.prompt_stack.messages.message import Message from griptape.engines import BaseExtractionEngine from griptape.utils import J2 -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.rules import Ruleset @@ -58,9 +59,7 @@ def _extract_rec( if self.prompt_driver.tokenizer.count_input_tokens_left(full_text) >= self.min_response_tokens: extractions.extend( self.json_to_text_artifacts( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(full_text, role=PromptStack.USER_ROLE)]) - ).value + self.prompt_driver.run(PromptStack(messages=[Message(full_text, role=Message.USER_ROLE)])).value ) ) @@ -75,9 +74,7 @@ def _extract_rec( extractions.extend( self.json_to_text_artifacts( - self.prompt_driver.run( - PromptStack(inputs=[PromptStack.Input(partial_text, role=PromptStack.USER_ROLE)]) - ).value + self.prompt_driver.run(PromptStack(messages=[Message(partial_text, role=Message.USER_ROLE)])).value ) ) diff --git a/griptape/engines/query/base_query_engine.py b/griptape/engines/query/base_query_engine.py deleted file mode 100644 index 61a488547..000000000 --- a/griptape/engines/query/base_query_engine.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import annotations -from abc import ABC, abstractmethod -from attrs import define -from typing import Optional -from griptape.artifacts import TextArtifact, ListArtifact -from griptape.rules import Ruleset - - -@define -class BaseQueryEngine(ABC): - @abstractmethod - def query( - self, - query: str, - namespace: Optional[str] = None, - *, - rulesets: Optional[list[Ruleset]] = None, - top_n: Optional[int] = None, - filter: Optional[dict] = None, - ) -> TextArtifact: ... - - @abstractmethod - def load_artifacts(self, namespace: str) -> ListArtifact: ... - - @abstractmethod - def upsert_text_artifact(self, artifact: TextArtifact, namespace: Optional[str] = None) -> str: ... - - @abstractmethod - def upsert_text_artifacts(self, artifacts: list[TextArtifact], namespace: str) -> None: ... diff --git a/griptape/engines/query/vector_query_engine.py b/griptape/engines/query/vector_query_engine.py deleted file mode 100644 index de93b5af4..000000000 --- a/griptape/engines/query/vector_query_engine.py +++ /dev/null @@ -1,95 +0,0 @@ -from __future__ import annotations -from typing import TYPE_CHECKING, Optional -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact -from griptape.utils import PromptStack -from griptape.engines import BaseQueryEngine -from griptape.utils.j2 import J2 -from griptape.rules import Ruleset - -if TYPE_CHECKING: - from griptape.drivers import BaseVectorStoreDriver, BasePromptDriver - - -@define -class VectorQueryEngine(BaseQueryEngine): - answer_token_offset: int = field(default=400, kw_only=True) - vector_store_driver: BaseVectorStoreDriver = field(kw_only=True) - prompt_driver: BasePromptDriver = field(kw_only=True) - user_template_generator: J2 = field(default=Factory(lambda: J2("engines/query/user.j2")), kw_only=True) - system_template_generator: J2 = field(default=Factory(lambda: J2("engines/query/system.j2")), kw_only=True) - - def query( - self, - query: str, - namespace: Optional[str] = None, - *, - rulesets: Optional[list[Ruleset]] = None, - metadata: Optional[str] = None, - top_n: Optional[int] = None, - filter: Optional[dict] = None, - ) -> TextArtifact: - tokenizer = self.prompt_driver.tokenizer - result = self.vector_store_driver.query(query, top_n, namespace, filter=filter) - artifacts = [ - artifact - for artifact in [BaseArtifact.from_json(r.meta["artifact"]) for r in result if r.meta] - if isinstance(artifact, TextArtifact) - ] - text_segments = [] - user_message = "" - system_message = "" - - for artifact in artifacts: - text_segments.append(artifact.value) - system_message = self.system_template_generator.render( - rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets), - metadata=metadata, - text_segments=text_segments, - ) - user_message = self.user_template_generator.render(query=query) - - message_token_count = self.prompt_driver.tokenizer.count_tokens( - self.prompt_driver.prompt_stack_to_string( - PromptStack( - inputs=[ - PromptStack.Input(system_message, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(user_message, role=PromptStack.USER_ROLE), - ] - ) - ) - ) - - if message_token_count + self.answer_token_offset >= tokenizer.max_input_tokens: - text_segments.pop() - - system_message = self.system_template_generator.render( - rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets), - metadata=metadata, - text_segments=text_segments, - ) - - break - - return self.prompt_driver.run( - PromptStack( - inputs=[ - PromptStack.Input(system_message, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(user_message, role=PromptStack.USER_ROLE), - ] - ) - ) - - def upsert_text_artifact(self, artifact: TextArtifact, namespace: Optional[str] = None) -> str: - result = self.vector_store_driver.upsert_text_artifact(artifact, namespace=namespace) - - return result - - def upsert_text_artifacts(self, artifacts: list[TextArtifact], namespace: str) -> None: - self.vector_store_driver.upsert_text_artifacts({namespace: artifacts}) - - def load_artifacts(self, namespace: str) -> ListArtifact: - result = self.vector_store_driver.load_entries(namespace) - artifacts = [BaseArtifact.from_json(r.meta["artifact"]) for r in result if r.meta and r.meta.get("artifact")] - - return ListArtifact([a for a in artifacts if isinstance(a, TextArtifact)]) diff --git a/griptape/engines/rag/__init__.py b/griptape/engines/rag/__init__.py new file mode 100644 index 000000000..f009772fb --- /dev/null +++ b/griptape/engines/rag/__init__.py @@ -0,0 +1,4 @@ +from .rag_context import RagContext +from .rag_engine import RagEngine + +__all__ = ["RagContext", "RagEngine"] diff --git a/griptape/engines/rag/modules/__init__.py b/griptape/engines/rag/modules/__init__.py new file mode 100644 index 000000000..4a180490d --- /dev/null +++ b/griptape/engines/rag/modules/__init__.py @@ -0,0 +1,33 @@ +from .base_rag_module import BaseRagModule +from .query.base_query_rag_module import BaseQueryRagModule +from .retrieval.base_retrieval_rag_module import BaseRetrievalRagModule +from .retrieval.base_rerank_rag_module import BaseRerankRagModule +from .retrieval.text_chunks_rerank_rag_module import TextChunksRerankRagModule +from .retrieval.vector_store_retrieval_rag_module import VectorStoreRetrievalRagModule +from .retrieval.text_loader_retrieval_rag_module import TextLoaderRetrievalRagModule +from .response.base_before_response_rag_module import BaseBeforeResponseRagModule +from .response.base_after_response_rag_module import BaseAfterResponseRagModule +from .response.base_response_rag_module import BaseResponseRagModule +from .response.prompt_response_rag_module import PromptResponseRagModule +from .response.rulesets_before_response_rag_module import RulesetsBeforeResponseRagModule +from .response.metadata_before_response_rag_module import MetadataBeforeResponseRagModule +from .response.text_chunks_response_rag_module import TextChunksResponseRagModule +from .response.footnote_prompt_response_rag_module import FootnotePromptResponseRagModule + +__all__ = [ + "BaseRagModule", + "BaseQueryRagModule", + "BaseRetrievalRagModule", + "BaseRerankRagModule", + "TextChunksRerankRagModule", + "VectorStoreRetrievalRagModule", + "TextLoaderRetrievalRagModule", + "BaseBeforeResponseRagModule", + "BaseAfterResponseRagModule", + "BaseResponseRagModule", + "PromptResponseRagModule", + "RulesetsBeforeResponseRagModule", + "MetadataBeforeResponseRagModule", + "TextChunksResponseRagModule", + "FootnotePromptResponseRagModule", +] diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py new file mode 100644 index 000000000..9bdcb6372 --- /dev/null +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -0,0 +1,28 @@ +from abc import ABC +from concurrent import futures +from typing import Callable, Any, Optional +from attrs import define, field, Factory +from griptape.engines.rag import RagContext +from griptape.common import PromptStack, Message + + +@define(kw_only=True) +class BaseRagModule(ABC): + name: str = field(default=Factory(lambda self: self.__class__.__name__, takes_self=True), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()) + ) + + def generate_query_prompt_stack(self, system_prompt: str, query: str) -> PromptStack: + return PromptStack( + messages=[Message(system_prompt, role=Message.SYSTEM_ROLE), Message(query, role=Message.USER_ROLE)] + ) + + def get_context_param(self, context: RagContext, key: str) -> Optional[Any]: + return context.module_configs.get(self.name, {}).get(key) + + def set_context_param(self, context: RagContext, key: str, value: Any) -> None: + if not isinstance(context.module_configs.get(self.name), dict): + context.module_configs[self.name] = {} + + context.module_configs[self.name][key] = value diff --git a/griptape/engines/rag/modules/query/__init__.py b/griptape/engines/rag/modules/query/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/engines/rag/modules/query/base_query_rag_module.py b/griptape/engines/rag/modules/query/base_query_rag_module.py new file mode 100644 index 000000000..195bba6bd --- /dev/null +++ b/griptape/engines/rag/modules/query/base_query_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseQueryRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/response/__init__.py b/griptape/engines/rag/modules/response/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/engines/rag/modules/response/base_after_response_rag_module.py b/griptape/engines/rag/modules/response/base_after_response_rag_module.py new file mode 100644 index 000000000..03d906204 --- /dev/null +++ b/griptape/engines/rag/modules/response/base_after_response_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseAfterResponseRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/response/base_before_response_rag_module.py b/griptape/engines/rag/modules/response/base_before_response_rag_module.py new file mode 100644 index 000000000..2a16b68d0 --- /dev/null +++ b/griptape/engines/rag/modules/response/base_before_response_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseBeforeResponseRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/response/base_response_rag_module.py b/griptape/engines/rag/modules/response/base_response_rag_module.py new file mode 100644 index 000000000..72a7dce1b --- /dev/null +++ b/griptape/engines/rag/modules/response/base_response_rag_module.py @@ -0,0 +1,10 @@ +from abc import ABC, abstractmethod +from attrs import define +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseResponseRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... diff --git a/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py b/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py new file mode 100644 index 000000000..c64c8e5ee --- /dev/null +++ b/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py @@ -0,0 +1,18 @@ +from attrs import define + +from griptape import utils +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import PromptResponseRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class FootnotePromptResponseRagModule(PromptResponseRagModule): + def default_system_template_generator(self, context: RagContext, artifacts: list[TextArtifact]) -> str: + return J2("engines/rag/modules/response/footnote_prompt/system.j2").render( + text_chunk_artifacts=artifacts, + references=utils.references_from_artifacts(artifacts), + before_system_prompt="\n\n".join(context.before_query), + after_system_prompt="\n\n".join(context.after_query), + ) diff --git a/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py new file mode 100644 index 000000000..7bd1cf0a9 --- /dev/null +++ b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py @@ -0,0 +1,19 @@ +from typing import Optional +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseBeforeResponseRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class MetadataBeforeResponseRagModule(BaseBeforeResponseRagModule): + metadata: Optional[str] = field(default=None) + + def run(self, context: RagContext) -> RagContext: + context_metadata = self.get_context_param(context, "metadata") + metadata = self.metadata if context_metadata is None else context_metadata + + if metadata is not None: + context.before_query.append(J2("engines/rag/modules/response/metadata/system.j2").render(metadata=metadata)) + + return context diff --git a/griptape/engines/rag/modules/response/prompt_response_rag_module.py b/griptape/engines/rag/modules/response/prompt_response_rag_module.py new file mode 100644 index 000000000..8552ab904 --- /dev/null +++ b/griptape/engines/rag/modules/response/prompt_response_rag_module.py @@ -0,0 +1,53 @@ +from typing import Callable +from attrs import define, field, Factory +from griptape.artifacts.text_artifact import TextArtifact +from griptape.drivers import BasePromptDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseResponseRagModule +from griptape.utils import J2 + + +@define(kw_only=True) +class PromptResponseRagModule(BaseResponseRagModule): + answer_token_offset: int = field(default=400) + prompt_driver: BasePromptDriver = field() + generate_system_template: Callable[[RagContext, list[TextArtifact]], str] = field( + default=Factory(lambda self: self.default_system_template_generator, takes_self=True) + ) + + def run(self, context: RagContext) -> RagContext: + query = context.query + tokenizer = self.prompt_driver.tokenizer + included_chunks = [] + system_prompt = self.generate_system_template(context, included_chunks) + + for artifact in context.text_chunks: + included_chunks.append(artifact) + + system_prompt = self.generate_system_template(context, included_chunks) + message_token_count = self.prompt_driver.tokenizer.count_tokens( + self.prompt_driver.prompt_stack_to_string(self.generate_query_prompt_stack(system_prompt, query)) + ) + + if message_token_count + self.answer_token_offset >= tokenizer.max_input_tokens: + included_chunks.pop() + + system_prompt = self.generate_system_template(context, included_chunks) + + break + + output = self.prompt_driver.run(self.generate_query_prompt_stack(system_prompt, query)).to_artifact() + + if isinstance(output, TextArtifact): + context.output = output + else: + raise ValueError("Prompt driver did not return a TextArtifact") + + return context + + def default_system_template_generator(self, context: RagContext, artifacts: list[TextArtifact]) -> str: + return J2("engines/rag/modules/response/prompt/system.j2").render( + text_chunks=[c.to_text() for c in artifacts], + before_system_prompt="\n\n".join(context.before_query), + after_system_prompt="\n\n".join(context.after_query), + ) diff --git a/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py new file mode 100644 index 000000000..27a421c1b --- /dev/null +++ b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py @@ -0,0 +1,15 @@ +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseBeforeResponseRagModule +from griptape.rules import Ruleset +from griptape.utils import J2 + + +@define +class RulesetsBeforeResponseRagModule(BaseBeforeResponseRagModule): + rulesets: list[Ruleset] = field(kw_only=True) + + def run(self, context: RagContext) -> RagContext: + context.before_query.append(J2("rulesets/rulesets.j2").render(rulesets=self.rulesets)) + + return context diff --git a/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py b/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py new file mode 100644 index 000000000..699aa1124 --- /dev/null +++ b/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py @@ -0,0 +1,12 @@ +from attrs import define +from griptape.artifacts import ListArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseResponseRagModule + + +@define(kw_only=True) +class TextChunksResponseRagModule(BaseResponseRagModule): + def run(self, context: RagContext) -> RagContext: + context.output = ListArtifact(context.text_chunks) + + return context diff --git a/griptape/engines/rag/modules/retrieval/__init__.py b/griptape/engines/rag/modules/retrieval/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py b/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py new file mode 100644 index 000000000..8ecf9f046 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py @@ -0,0 +1,16 @@ +from abc import ABC, abstractmethod +from typing import Sequence + +from attrs import define, field +from griptape.artifacts import BaseArtifact +from griptape.drivers import BaseRerankDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseRerankRagModule(BaseRagModule, ABC): + rerank_driver: BaseRerankDriver = field() + + @abstractmethod + def run(self, context: RagContext) -> Sequence[BaseArtifact]: ... diff --git a/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py new file mode 100644 index 000000000..f11537d9f --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py @@ -0,0 +1,12 @@ +from abc import ABC, abstractmethod +from typing import Sequence +from attrs import define +from griptape.artifacts import BaseArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseRetrievalRagModule(BaseRagModule, ABC): + @abstractmethod + def run(self, context: RagContext) -> Sequence[BaseArtifact]: ... diff --git a/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py b/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py new file mode 100644 index 000000000..b78c3a880 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py @@ -0,0 +1,12 @@ +from typing import Sequence + +from attrs import define +from griptape.artifacts import BaseArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRerankRagModule + + +@define(kw_only=True) +class TextChunksRerankRagModule(BaseRerankRagModule): + def run(self, context: RagContext) -> Sequence[BaseArtifact]: + return self.rerank_driver.run(context.query, context.text_chunks) diff --git a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py new file mode 100644 index 000000000..a37910da6 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py @@ -0,0 +1,41 @@ +from __future__ import annotations +import uuid +from typing import TYPE_CHECKING, Sequence, Any, Callable +from attrs import define, field, Factory +from griptape import utils +from griptape.artifacts import TextArtifact, ErrorArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRetrievalRagModule + +if TYPE_CHECKING: + from griptape.drivers import BaseVectorStoreDriver + from griptape.loaders import BaseTextLoader + + +@define(kw_only=True) +class TextLoaderRetrievalRagModule(BaseRetrievalRagModule): + loader: BaseTextLoader = field() + vector_store_driver: BaseVectorStoreDriver = field() + source: Any = field() + query_params: dict[str, Any] = field(factory=dict) + process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], Sequence[TextArtifact]] = field( + default=Factory(lambda: lambda es: [e.to_artifact() for e in es]) + ) + + def run(self, context: RagContext) -> Sequence[TextArtifact]: + namespace = uuid.uuid4().hex + context_source = self.get_context_param(context, "source") + source = self.source if context_source is None else context_source + + query_params = utils.dict_merge(self.query_params, self.get_context_param(context, "query_params")) + + query_params["namespace"] = namespace + + loader_output = self.loader.load(source) + + if isinstance(loader_output, ErrorArtifact): + raise Exception(loader_output.to_text() if loader_output.exception is None else loader_output.exception) + else: + self.vector_store_driver.upsert_text_artifacts({namespace: loader_output}) + + return self.process_query_output_fn(self.vector_store_driver.query(context.query, **query_params)) diff --git a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py new file mode 100644 index 000000000..96d249693 --- /dev/null +++ b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py @@ -0,0 +1,24 @@ +from __future__ import annotations +from typing import TYPE_CHECKING, Sequence, Any, Callable +from attrs import define, field, Factory +from griptape import utils +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRetrievalRagModule + +if TYPE_CHECKING: + from griptape.drivers import BaseVectorStoreDriver + + +@define(kw_only=True) +class VectorStoreRetrievalRagModule(BaseRetrievalRagModule): + vector_store_driver: BaseVectorStoreDriver = field() + query_params: dict[str, Any] = field(factory=dict) + process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], Sequence[TextArtifact]] = field( + default=Factory(lambda: lambda es: [e.to_artifact() for e in es]) + ) + + def run(self, context: RagContext) -> Sequence[TextArtifact]: + query_params = utils.dict_merge(self.query_params, self.get_context_param(context, "query_params")) + + return self.process_query_output_fn(self.vector_store_driver.query(context.query, **query_params)) diff --git a/griptape/engines/rag/rag_context.py b/griptape/engines/rag/rag_context.py new file mode 100644 index 000000000..c0658ad7b --- /dev/null +++ b/griptape/engines/rag/rag_context.py @@ -0,0 +1,35 @@ +from __future__ import annotations +from typing import Optional, TYPE_CHECKING +from attrs import define, field + +from griptape import utils +from griptape.common import Reference +from griptape.mixins import SerializableMixin + +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact, BaseArtifact + + +@define(kw_only=True) +class RagContext(SerializableMixin): + """Used by RagEngine stages and module to pass context that individual modules are expected to update in the `run` + method. + + Attributes: + query: Query provided by the user. + module_configs: Dictionary of module configs. First key should be a module name and the second a dictionary of config parameters. + before_query: An optional list of strings to add before the query in generation modules. + after_query: An optional list of strings to add after the query in generation modules. + text_chunks: A list of text chunks to pass around from the retrieval stage to the generation stage. + output: Final output from the generation stage. + """ + + query: str = field(metadata={"serializable": True}) + module_configs: dict[str, dict] = field(factory=dict, metadata={"serializable": True}) + before_query: list[str] = field(factory=list, metadata={"serializable": True}) + after_query: list[str] = field(factory=list, metadata={"serializable": True}) + text_chunks: list[TextArtifact] = field(factory=list, metadata={"serializable": True}) + output: Optional[BaseArtifact] = field(default=None, metadata={"serializable": True}) + + def get_references(self) -> list[Reference]: + return utils.references_from_artifacts(self.text_chunks) diff --git a/griptape/engines/rag/rag_engine.py b/griptape/engines/rag/rag_engine.py new file mode 100644 index 000000000..da8a2eebe --- /dev/null +++ b/griptape/engines/rag/rag_engine.py @@ -0,0 +1,43 @@ +from typing import Optional +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.stages import QueryRagStage, ResponseRagStage, RetrievalRagStage + + +@define(kw_only=True) +class RagEngine: + query_stage: Optional[QueryRagStage] = field(default=None) + retrieval_stage: Optional[RetrievalRagStage] = field(default=None) + response_stage: Optional[ResponseRagStage] = field(default=None) + + def __attrs_post_init__(self) -> None: + modules = [] + + if self.query_stage is not None: + modules.extend(self.query_stage.modules) + + if self.retrieval_stage is not None: + modules.extend(self.retrieval_stage.modules) + + if self.response_stage is not None: + modules.extend(self.response_stage.modules) + + module_names = [m.name for m in modules] + + if len(module_names) > len(set(module_names)): + raise ValueError("module names have to be unique") + + def process_query(self, query: str) -> RagContext: + return self.process(RagContext(query=query)) + + def process(self, context: RagContext) -> RagContext: + if self.query_stage: + context = self.query_stage.run(context) + + if self.retrieval_stage: + context = self.retrieval_stage.run(context) + + if self.response_stage: + context = self.response_stage.run(context) + + return context diff --git a/griptape/engines/rag/stages/__init__.py b/griptape/engines/rag/stages/__init__.py new file mode 100644 index 000000000..14756563c --- /dev/null +++ b/griptape/engines/rag/stages/__init__.py @@ -0,0 +1,6 @@ +from .base_rag_stage import BaseRagStage +from .retrieval_rag_stage import RetrievalRagStage +from .query_rag_stage import QueryRagStage +from .response_rag_stage import ResponseRagStage + +__all__ = ["BaseRagStage", "RetrievalRagStage", "QueryRagStage", "ResponseRagStage"] diff --git a/griptape/engines/rag/stages/base_rag_stage.py b/griptape/engines/rag/stages/base_rag_stage.py new file mode 100644 index 000000000..4db996e30 --- /dev/null +++ b/griptape/engines/rag/stages/base_rag_stage.py @@ -0,0 +1,20 @@ +from abc import ABC, abstractmethod +from concurrent import futures +from typing import Callable +from attrs import define, field, Factory +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRagModule + + +@define(kw_only=True) +class BaseRagStage(ABC): + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()) + ) + + @abstractmethod + def run(self, context: RagContext) -> RagContext: ... + + @property + @abstractmethod + def modules(self) -> list[BaseRagModule]: ... diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py new file mode 100644 index 000000000..84c200bc8 --- /dev/null +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -0,0 +1,23 @@ +import logging +from attrs import define, field +from griptape import utils +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseQueryRagModule, BaseRagModule +from griptape.engines.rag.stages import BaseRagStage + + +@define(kw_only=True) +class QueryRagStage(BaseRagStage): + query_modules: list[BaseQueryRagModule] = field() + + @property + def modules(self) -> list[BaseRagModule]: + return self.query_modules # pyright: ignore + + def run(self, context: RagContext) -> RagContext: + logging.info(f"QueryStage: running {len(self.query_modules)} query generation modules in parallel") + + with self.futures_executor_fn() as executor: + utils.execute_futures_list([executor.submit(r.run, context) for r in self.query_modules]) + + return context diff --git a/griptape/engines/rag/stages/response_rag_stage.py b/griptape/engines/rag/stages/response_rag_stage.py new file mode 100644 index 000000000..aa0a15dfc --- /dev/null +++ b/griptape/engines/rag/stages/response_rag_stage.py @@ -0,0 +1,46 @@ +import logging +from attrs import define, field +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import ( + BaseResponseRagModule, + BaseBeforeResponseRagModule, + BaseAfterResponseRagModule, + BaseRagModule, +) +from griptape.engines.rag.stages import BaseRagStage + + +@define(kw_only=True) +class ResponseRagStage(BaseRagStage): + before_response_modules: list[BaseBeforeResponseRagModule] = field(factory=list) + response_module: BaseResponseRagModule = field() + after_response_modules: list[BaseAfterResponseRagModule] = field(factory=list) + + @property + def modules(self) -> list[BaseRagModule]: + ms = [] + + ms.extend(self.before_response_modules) + ms.extend(self.after_response_modules) + + if self.response_module is not None: + ms.append(self.response_module) + + return ms + + def run(self, context: RagContext) -> RagContext: + logging.info(f"GenerationStage: running {len(self.before_response_modules)} before modules sequentially") + + for generator in self.before_response_modules: + context = generator.run(context) + + logging.info("GenerationStage: running generation module") + + context = self.response_module.run(context) + + logging.info(f"GenerationStage: running {len(self.after_response_modules)} after modules sequentially") + + for generator in self.after_response_modules: + context = generator.run(context) + + return context diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py new file mode 100644 index 000000000..8fe376cd1 --- /dev/null +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -0,0 +1,59 @@ +import itertools +import logging +from typing import Optional +from attrs import define, field +from griptape import utils +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import BaseRerankRagModule, BaseRagModule +from griptape.engines.rag.modules import BaseRetrievalRagModule +from griptape.engines.rag.stages import BaseRagStage + + +@define(kw_only=True) +class RetrievalRagStage(BaseRagStage): + retrieval_modules: list[BaseRetrievalRagModule] = field() + rerank_module: Optional[BaseRerankRagModule] = field(default=None) + max_chunks: Optional[int] = field(default=None) + + @property + def modules(self) -> list[BaseRagModule]: + ms = [] + + ms.extend(self.retrieval_modules) + + if self.rerank_module is not None: + ms.append(self.rerank_module) + + return ms + + def run(self, context: RagContext) -> RagContext: + logging.info(f"RetrievalStage: running {len(self.retrieval_modules)} retrieval modules in parallel") + + with self.futures_executor_fn() as executor: + results = utils.execute_futures_list([executor.submit(r.run, context) for r in self.retrieval_modules]) + + # flatten the list of lists + results = list(itertools.chain.from_iterable(results)) + + # deduplicate the list + chunks_before_dedup = len(results) + results = list({str(c.value): c for c in results}.values()) + chunks_after_dedup = len(results) + + logging.info( + f"RetrievalStage: deduplicated {chunks_before_dedup - chunks_after_dedup} " + f"chunks ({chunks_before_dedup} - {chunks_after_dedup})" + ) + + context.text_chunks = [a for a in results if isinstance(a, TextArtifact)] + + if self.rerank_module: + logging.info(f"RetrievalStage: running rerank module on {chunks_after_dedup} chunks") + + context.text_chunks = [a for a in self.rerank_module.run(context) if isinstance(a, TextArtifact)] + + if self.max_chunks: + context.text_chunks = context.text_chunks[: self.max_chunks] + + return context diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 9d3e8db78..51259e444 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -2,7 +2,8 @@ from attrs import define, Factory, field from griptape.artifacts import TextArtifact, ListArtifact from griptape.chunkers import BaseChunker, TextChunker -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.common.prompt_stack.messages.message import Message from griptape.drivers import BasePromptDriver from griptape.engines import BaseSummaryEngine from griptape.utils import J2 @@ -60,14 +61,19 @@ def summarize_artifacts_rec( self.prompt_driver.tokenizer.count_input_tokens_left(user_prompt + system_prompt) >= self.min_response_tokens ): - return self.prompt_driver.run( + result = self.prompt_driver.run( PromptStack( - inputs=[ - PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(user_prompt, role=PromptStack.USER_ROLE), + messages=[ + Message(system_prompt, role=Message.SYSTEM_ROLE), + Message(user_prompt, role=Message.USER_ROLE), ] ) - ) + ).to_artifact() + + if isinstance(result, TextArtifact): + return result + else: + raise ValueError("Prompt driver did not return a TextArtifact") else: chunks = self.chunker.chunk(artifacts_text) @@ -77,9 +83,9 @@ def summarize_artifacts_rec( chunks[1:], self.prompt_driver.run( PromptStack( - inputs=[ - PromptStack.Input(system_prompt, role=PromptStack.SYSTEM_ROLE), - PromptStack.Input(partial_text, role=PromptStack.USER_ROLE), + messages=[ + Message(system_prompt, role=Message.SYSTEM_ROLE), + Message(partial_text, role=Message.USER_ROLE), ] ) ).value, diff --git a/griptape/events/base_prompt_event.py b/griptape/events/base_prompt_event.py index b9dcd0c57..4a44599cc 100644 --- a/griptape/events/base_prompt_event.py +++ b/griptape/events/base_prompt_event.py @@ -7,4 +7,3 @@ @define class BasePromptEvent(BaseEvent, ABC): model: str = field(kw_only=True, metadata={"serializable": True}) - token_count: int = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/events/finish_prompt_event.py b/griptape/events/finish_prompt_event.py index 83bc1b9ef..79e338871 100644 --- a/griptape/events/finish_prompt_event.py +++ b/griptape/events/finish_prompt_event.py @@ -1,7 +1,10 @@ from attrs import define, field +from typing import Optional from griptape.events.base_prompt_event import BasePromptEvent @define class FinishPromptEvent(BasePromptEvent): result: str = field(kw_only=True, metadata={"serializable": True}) + input_token_count: Optional[float] = field(kw_only=True, metadata={"serializable": True}) + output_token_count: Optional[float] = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/events/start_prompt_event.py b/griptape/events/start_prompt_event.py index 7ab418adb..35dae95d6 100644 --- a/griptape/events/start_prompt_event.py +++ b/griptape/events/start_prompt_event.py @@ -5,10 +5,9 @@ from griptape.events.base_prompt_event import BasePromptEvent if TYPE_CHECKING: - from griptape.utils import PromptStack + from griptape.common import PromptStack @define class StartPromptEvent(BasePromptEvent): prompt_stack: PromptStack = field(kw_only=True, metadata={"serializable": True}) - prompt: str = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/loaders/base_loader.py b/griptape/loaders/base_loader.py index 1648b8f26..00fbf07ec 100644 --- a/griptape/loaders/base_loader.py +++ b/griptape/loaders/base_loader.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from concurrent import futures -from typing import Any, Optional +from typing import Any, Optional, Callable from collections.abc import Mapping, Sequence from attrs import define, field, Factory @@ -14,7 +14,9 @@ @define class BaseLoader(ABC): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) encoding: Optional[str] = field(default=None, kw_only=True) @abstractmethod @@ -26,12 +28,11 @@ def load_collection( # Create a dictionary before actually submitting the jobs to the executor # to avoid duplicate work. sources_by_key = {self.to_key(source): source for source in sources} - return execute_futures_dict( - { - key: self.futures_executor.submit(self.load, source, *args, **kwargs) - for key, source in sources_by_key.items() - } - ) + + with self.futures_executor_fn() as executor: + return execute_futures_dict( + {key: executor.submit(self.load, source, *args, **kwargs) for key, source in sources_by_key.items()} + ) def to_key(self, source: Any, *args, **kwargs) -> str: if isinstance(source, bytes): diff --git a/griptape/loaders/base_text_loader.py b/griptape/loaders/base_text_loader.py index f09b57902..4f2a93183 100644 --- a/griptape/loaders/base_text_loader.py +++ b/griptape/loaders/base_text_loader.py @@ -1,13 +1,11 @@ from __future__ import annotations - -from abc import ABC +from abc import ABC, abstractmethod from typing import Any, Optional, Union, cast - from attrs import define, field, Factory - from griptape.artifacts import TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact from griptape.chunkers import TextChunker, BaseChunker +from griptape.common import Reference from griptape.drivers import BaseEmbeddingDriver from griptape.loaders import BaseLoader from griptape.tokenizers import OpenAiTokenizer @@ -32,6 +30,10 @@ class BaseTextLoader(BaseLoader, ABC): ) embedding_driver: Optional[BaseEmbeddingDriver] = field(default=None, kw_only=True) encoding: str = field(default="utf-8", kw_only=True) + reference: Optional[Reference] = field(default=None, kw_only=True) + + @abstractmethod + def load(self, source: Any, *args, **kwargs) -> ErrorArtifact | list[TextArtifact]: ... def load_collection(self, sources: list[Any], *args, **kwargs) -> dict[str, ErrorArtifact | list[TextArtifact]]: return cast( @@ -41,17 +43,16 @@ def load_collection(self, sources: list[Any], *args, **kwargs) -> dict[str, Erro def _text_to_artifacts(self, text: str) -> list[TextArtifact]: artifacts = [] - if self.chunker: - chunks = self.chunker.chunk(text) - else: - chunks = [TextArtifact(text)] + chunks = self.chunker.chunk(text) if self.chunker else [TextArtifact(text)] - if self.embedding_driver: - for chunk in chunks: + for chunk in chunks: + if self.embedding_driver: chunk.generate_embedding(self.embedding_driver) - for chunk in chunks: + chunk.reference = self.reference + chunk.encoding = self.encoding + artifacts.append(chunk) return artifacts diff --git a/griptape/loaders/sql_loader.py b/griptape/loaders/sql_loader.py index c20fb022d..e6979e324 100644 --- a/griptape/loaders/sql_loader.py +++ b/griptape/loaders/sql_loader.py @@ -16,10 +16,7 @@ def load(self, source: str, *args, **kwargs) -> list[CsvRowArtifact]: rows = self.sql_driver.execute_query(source) artifacts = [] - if rows: - chunks = [CsvRowArtifact(row.cells) for row in rows] - else: - chunks = [] + chunks = [CsvRowArtifact(row.cells) for row in rows] if rows else [] if self.embedding_driver: for chunk in chunks: diff --git a/griptape/memory/structure/base_conversation_memory.py b/griptape/memory/structure/base_conversation_memory.py index f8cc51743..a8133d64b 100644 --- a/griptape/memory/structure/base_conversation_memory.py +++ b/griptape/memory/structure/base_conversation_memory.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Optional from attrs import define, field from griptape.memory.structure import Run -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.mixins import SerializableMixin from abc import ABC, abstractmethod @@ -47,7 +47,7 @@ def try_add_run(self, run: Run) -> None: ... def to_prompt_stack(self, last_n: Optional[int] = None) -> PromptStack: ... def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = None) -> PromptStack: - """Add the Conversation Memory runs to the Prompt Stack by modifying the inputs in place. + """Add the Conversation Memory runs to the Prompt Stack by modifying the messages in place. If autoprune is enabled, this will fit as many Conversation Memory runs into the Prompt Stack as possible without exceeding the token limit. @@ -67,15 +67,15 @@ def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = # Try to determine how many Conversation Memory runs we can # fit into the Prompt Stack without exceeding the token limit. while should_prune and num_runs_to_fit_in_prompt > 0: - temp_stack.inputs = prompt_stack.inputs.copy() + temp_stack.messages = prompt_stack.messages.copy() # Add n runs from Conversation Memory. # Where we insert into the Prompt Stack doesn't matter here # since we only care about the total token count. - memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).inputs - temp_stack.inputs.extend(memory_inputs) + memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).messages + temp_stack.messages.extend(memory_inputs) - # Convert the prompt stack into tokens left. + # Convert the Prompt Stack into tokens left. tokens_left = prompt_driver.tokenizer.count_input_tokens_left( prompt_driver.prompt_stack_to_string(temp_stack) ) @@ -87,10 +87,10 @@ def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = num_runs_to_fit_in_prompt -= 1 if num_runs_to_fit_in_prompt: - memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).inputs + memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).messages if index: - prompt_stack.inputs[index:index] = memory_inputs + prompt_stack.messages[index:index] = memory_inputs else: - prompt_stack.inputs.extend(memory_inputs) + prompt_stack.messages.extend(memory_inputs) return prompt_stack diff --git a/griptape/memory/structure/conversation_memory.py b/griptape/memory/structure/conversation_memory.py index 94e73d80c..42d160abd 100644 --- a/griptape/memory/structure/conversation_memory.py +++ b/griptape/memory/structure/conversation_memory.py @@ -2,7 +2,7 @@ from attrs import define from typing import Optional from griptape.memory.structure import Run, BaseConversationMemory -from griptape.utils import PromptStack +from griptape.common import PromptStack @define @@ -18,6 +18,6 @@ def to_prompt_stack(self, last_n: Optional[int] = None) -> PromptStack: prompt_stack = PromptStack() runs = self.runs[-last_n:] if last_n else self.runs for run in runs: - prompt_stack.add_user_input(run.input) - prompt_stack.add_assistant_input(run.output) + prompt_stack.add_user_message(run.input) + prompt_stack.add_assistant_message(run.output) return prompt_stack diff --git a/griptape/memory/structure/run.py b/griptape/memory/structure/run.py index c5a2b9b55..b91df2ae9 100644 --- a/griptape/memory/structure/run.py +++ b/griptape/memory/structure/run.py @@ -1,10 +1,11 @@ import uuid from attrs import define, field, Factory +from griptape.artifacts.base_artifact import BaseArtifact from griptape.mixins import SerializableMixin @define class Run(SerializableMixin): id: str = field(default=Factory(lambda: uuid.uuid4().hex), kw_only=True, metadata={"serializable": True}) - input: str = field(kw_only=True, metadata={"serializable": True}) - output: str = field(kw_only=True, metadata={"serializable": True}) + input: BaseArtifact = field(kw_only=True, metadata={"serializable": True}) + output: BaseArtifact = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/memory/structure/summary_conversation_memory.py b/griptape/memory/structure/summary_conversation_memory.py index e4d5597d5..b88a4b4e6 100644 --- a/griptape/memory/structure/summary_conversation_memory.py +++ b/griptape/memory/structure/summary_conversation_memory.py @@ -2,7 +2,9 @@ import logging from typing import TYPE_CHECKING, Optional from attrs import define, field, Factory -from griptape.utils import J2, PromptStack +from griptape.common.prompt_stack.messages.message import Message +from griptape.utils import J2 +from griptape.common import PromptStack from griptape.memory.structure import ConversationMemory if TYPE_CHECKING: @@ -37,11 +39,11 @@ def prompt_driver(self, value: BasePromptDriver) -> None: def to_prompt_stack(self, last_n: Optional[int] = None) -> PromptStack: stack = PromptStack() if self.summary: - stack.add_user_input(self.summary_template_generator.render(summary=self.summary)) + stack.add_user_message(self.summary_template_generator.render(summary=self.summary)) for r in self.unsummarized_runs(last_n): - stack.add_user_input(r.input) - stack.add_assistant_input(r.output) + stack.add_user_message(r.input) + stack.add_assistant_message(r.output) return stack @@ -73,7 +75,7 @@ def summarize_runs(self, previous_summary: str | None, runs: list[Run]) -> str | if len(runs) > 0: summary = self.summarize_conversation_template_generator.render(summary=previous_summary, runs=runs) return self.prompt_driver.run( - prompt_stack=PromptStack(inputs=[PromptStack.Input(summary, role=PromptStack.USER_ROLE)]) + prompt_stack=PromptStack(messages=[Message(summary, role=Message.USER_ROLE)]) ).to_text() else: return previous_summary diff --git a/griptape/memory/task/storage/base_artifact_storage.py b/griptape/memory/task/storage/base_artifact_storage.py index fbd226363..e8378fee4 100644 --- a/griptape/memory/task/storage/base_artifact_storage.py +++ b/griptape/memory/task/storage/base_artifact_storage.py @@ -20,4 +20,4 @@ def can_store(self, artifact: BaseArtifact) -> bool: ... def summarize(self, namespace: str) -> TextArtifact | InfoArtifact: ... @abstractmethod - def query(self, namespace: str, query: str, metadata: Any = None) -> TextArtifact | InfoArtifact: ... + def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifact: ... diff --git a/griptape/memory/task/storage/blob_artifact_storage.py b/griptape/memory/task/storage/blob_artifact_storage.py index 79b5798df..9d09e17fa 100644 --- a/griptape/memory/task/storage/blob_artifact_storage.py +++ b/griptape/memory/task/storage/blob_artifact_storage.py @@ -26,5 +26,5 @@ def load_artifacts(self, namespace: str) -> ListArtifact: def summarize(self, namespace: str) -> InfoArtifact: return InfoArtifact("can't summarize artifacts") - def query(self, namespace: str, query: str, metadata: Any = None) -> InfoArtifact: + def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifact: return InfoArtifact("can't query artifacts") diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 3b3162751..0d135bcbd 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -1,36 +1,69 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any, Optional from attrs import define, field -from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact +from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact, InfoArtifact +from griptape.drivers import BaseVectorStoreDriver +from griptape.engines.rag import RagEngine, RagContext from griptape.memory.task.storage import BaseArtifactStorage if TYPE_CHECKING: - from griptape.engines import BaseSummaryEngine, CsvExtractionEngine, JsonExtractionEngine, VectorQueryEngine + from griptape.engines import BaseSummaryEngine, CsvExtractionEngine, JsonExtractionEngine -@define +@define(kw_only=True) class TextArtifactStorage(BaseArtifactStorage): - query_engine: VectorQueryEngine = field(kw_only=True) - summary_engine: Optional[BaseSummaryEngine] = field(kw_only=True, default=None) - csv_extraction_engine: Optional[CsvExtractionEngine] = field(kw_only=True, default=None) - json_extraction_engine: Optional[JsonExtractionEngine] = field(kw_only=True, default=None) + vector_store_driver: BaseVectorStoreDriver = field() + rag_engine: Optional[RagEngine] = field(default=None) + retrieval_rag_module_name: Optional[str] = field(default=None) + summary_engine: Optional[BaseSummaryEngine] = field(default=None) + csv_extraction_engine: Optional[CsvExtractionEngine] = field(default=None) + json_extraction_engine: Optional[JsonExtractionEngine] = field(default=None) + + @rag_engine.validator # pyright: ignore + def validate_rag_engine(self, _, rag_engine: str) -> None: + if rag_engine is not None and self.retrieval_rag_module_name is None: + raise ValueError("You have to set retrieval_rag_module_name if rag_engine is provided") def can_store(self, artifact: BaseArtifact) -> bool: return isinstance(artifact, TextArtifact) def store_artifact(self, namespace: str, artifact: BaseArtifact) -> None: if isinstance(artifact, TextArtifact): - self.query_engine.upsert_text_artifact(artifact, namespace) + self.vector_store_driver.upsert_text_artifact(artifact, namespace) else: raise ValueError("Artifact must be of instance TextArtifact") def load_artifacts(self, namespace: str) -> ListArtifact: - return self.query_engine.load_artifacts(namespace) + return self.vector_store_driver.load_artifacts(namespace) def summarize(self, namespace: str) -> TextArtifact: if self.summary_engine is None: raise ValueError("Summary engine is not set.") + return self.summary_engine.summarize_artifacts(self.load_artifacts(namespace)) - def query(self, namespace: str, query: str, metadata: Any = None) -> TextArtifact: - return self.query_engine.query(namespace=namespace, query=query, metadata=str(metadata) if metadata else None) + def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifact: + if self.rag_engine is None: + raise ValueError("rag_engine is not set") + + if self.retrieval_rag_module_name is None: + raise ValueError("retrieval_rag_module_name is not set") + + result = self.rag_engine.process( + RagContext( + query=query, + module_configs={ + self.retrieval_rag_module_name: { + "query_params": { + "namespace": namespace, + "metadata": None if metadata is None else str(metadata), + } + } + }, + ) + ).output + + if result is None: + return InfoArtifact("Empty output") + else: + return result diff --git a/griptape/memory/task/task_memory.py b/griptape/memory/task/task_memory.py index 2f1fdbe16..df9c9be30 100644 --- a/griptape/memory/task/task_memory.py +++ b/griptape/memory/task/task_memory.py @@ -124,7 +124,7 @@ def summarize_namespace(self, namespace: str) -> TextArtifact | InfoArtifact: else: return InfoArtifact("Can't find memory content") - def query_namespace(self, namespace: str, query: str) -> TextArtifact | InfoArtifact: + def query_namespace(self, namespace: str, query: str) -> BaseArtifact: storage = self.namespace_storage.get(namespace) if storage: diff --git a/griptape/mixins/rule_mixin.py b/griptape/mixins/rule_mixin.py index a89309a15..0cc696242 100644 --- a/griptape/mixins/rule_mixin.py +++ b/griptape/mixins/rule_mixin.py @@ -49,10 +49,7 @@ def all_rulesets(self) -> list[Ruleset]: if self.rulesets: task_rulesets = self.rulesets elif self.rules: - if structure_rulesets: - task_ruleset_name = self.ADDITIONAL_RULESET_NAME - else: - task_ruleset_name = self.DEFAULT_RULESET_NAME + task_ruleset_name = self.ADDITIONAL_RULESET_NAME if structure_rulesets else self.DEFAULT_RULESET_NAME task_rulesets = [Ruleset(name=task_ruleset_name, rules=self.rules)] diff --git a/griptape/mixins/serializable_mixin.py b/griptape/mixins/serializable_mixin.py index c7a0bf035..667ae752d 100644 --- a/griptape/mixins/serializable_mixin.py +++ b/griptape/mixins/serializable_mixin.py @@ -42,7 +42,7 @@ def get_schema(cls: type[T], subclass_name: Optional[str] = None) -> Schema: @classmethod def from_dict(cls: type[T], data: dict) -> T: - return cast(T, cls.get_schema(subclass_name=data["type"] if "type" in data else None).load(data)) + return cast(T, cls.get_schema(subclass_name=data.get("type")).load(data)) @classmethod def from_json(cls: type[T], data: str) -> T: diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 6ba23d6fe..e199a5c7e 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -59,7 +59,7 @@ def _get_field_for_type(cls, field_type: type) -> fields.Field | fields.Nested: if ABC in field_class.__bases__: return fields.Nested(PolymorphicSchema(inner_class=field_class), allow_none=optional) else: - return fields.Nested(cls.from_attrs_cls(field_type), allow_none=optional) + return fields.Nested(cls.from_attrs_cls(field_class), allow_none=optional) elif cls.is_list_sequence(field_class): if args: return fields.List(cls_or_instance=cls._get_field_for_type(args[0]), allow_none=optional) @@ -105,9 +105,10 @@ def _resolve_types(cls, attrs_cls: type) -> None: # These modules are required to avoid `NameError`s when resolving types. from griptape.drivers import BaseConversationMemoryDriver, BasePromptDriver from griptape.structures import Structure - from griptape.utils import PromptStack + from griptape.common import PromptStack, Message, Reference from griptape.tokenizers.base_tokenizer import BaseTokenizer from typing import Any + from griptape.artifacts import BaseArtifact boto3 = import_optional_dependency("boto3") if is_dependency_installed("boto3") else Any Client = import_optional_dependency("cohere").Client if is_dependency_installed("cohere") else Any @@ -116,13 +117,15 @@ def _resolve_types(cls, attrs_cls: type) -> None: attrs_cls, localns={ "PromptStack": PromptStack, - "Input": PromptStack.Input, + "Usage": Message.Usage, "Structure": Structure, "BaseConversationMemoryDriver": BaseConversationMemoryDriver, "BasePromptDriver": BasePromptDriver, "BaseTokenizer": BaseTokenizer, "boto3": boto3, "Client": Client, + "Reference": Reference, + "BaseArtifact": BaseArtifact, }, ) diff --git a/griptape/schemas/polymorphic_schema.py b/griptape/schemas/polymorphic_schema.py index 534ba8ffc..452e3001f 100644 --- a/griptape/schemas/polymorphic_schema.py +++ b/griptape/schemas/polymorphic_schema.py @@ -58,12 +58,12 @@ def _dump(self, obj, *, update_fields=True, **kwargs): obj_type = self.get_obj_type(obj) if not obj_type: - return (None, {"_schema": "Unknown object class: %s" % obj.__class__.__name__}) + return (None, {"_schema": f"Unknown object class: {obj.__class__.__name__}"}) type_schema = BaseSchema.from_attrs_cls(obj.__class__) if not type_schema: - return None, {"_schema": "Unsupported object type: %s" % obj_type} + return None, {"_schema": f"Unsupported object type: {obj_type}"} schema = type_schema if isinstance(type_schema, Schema) else type_schema() @@ -110,7 +110,7 @@ def load(self, data, *, many=None, partial=None, unknown=None, **kwargs): def _load(self, data, *, partial=None, unknown=None, **kwargs): if not isinstance(data, dict): - raise ValidationError({"_schema": "Invalid data type: %s" % data}) + raise ValidationError({"_schema": f"Invalid data type: {data}"}) data = dict(data) unknown = unknown or self.unknown @@ -121,7 +121,7 @@ def _load(self, data, *, partial=None, unknown=None, **kwargs): type_schema = self.inner_class.get_schema(data_type) if not type_schema: - raise ValidationError({self.type_field: ["Unsupported value: %s" % data_type]}) + raise ValidationError({self.type_field: [f"Unsupported value: {data_type}"]}) schema = type_schema if isinstance(type_schema, Schema) else type_schema() diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index d0446aff0..598aae37c 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -1,10 +1,12 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, Optional, Callable from attrs import define, field +from griptape.artifacts.text_artifact import TextArtifact from griptape.tools import BaseTool from griptape.memory.structure import Run from griptape.structures import Structure from griptape.tasks import PromptTask, ToolkitTask +from griptape.artifacts import BaseArtifact if TYPE_CHECKING: from griptape.tasks import BaseTask @@ -12,19 +14,25 @@ @define class Agent(Structure): - input_template: str = field(default=PromptTask.DEFAULT_INPUT_TEMPLATE) + input: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact] = field( + default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value="") + ) tools: list[BaseTool] = field(factory=list, kw_only=True) max_meta_memory_entries: Optional[int] = field(default=20, kw_only=True) + fail_fast: bool = field(default=False, kw_only=True) + + @fail_fast.validator # pyright: ignore + def validate_fail_fast(self, _, fail_fast: bool) -> None: + if fail_fast: + raise ValueError("Agents cannot fail fast, as they can only have 1 task.") def __attrs_post_init__(self) -> None: super().__attrs_post_init__() if len(self.tasks) == 0: if self.tools: - task = ToolkitTask( - self.input_template, tools=self.tools, max_meta_memory_entries=self.max_meta_memory_entries - ) + task = ToolkitTask(self.input, tools=self.tools, max_meta_memory_entries=self.max_meta_memory_entries) else: - task = PromptTask(self.input_template, max_meta_memory_entries=self.max_meta_memory_entries) + task = PromptTask(self.input, max_meta_memory_entries=self.max_meta_memory_entries) self.add_task(task) @@ -50,12 +58,7 @@ def try_run(self, *args) -> Agent: self.task.execute() if self.conversation_memory and self.output is not None: - if isinstance(self.task.input, tuple): - input_text = self.task.input[0].to_text() - else: - input_text = self.task.input.to_text() - - run = Run(input=input_text, output=self.task.output.to_text()) + run = Run(input=self.input_task.input, output=self.output) self.conversation_memory.add_run(run) diff --git a/griptape/structures/pipeline.py b/griptape/structures/pipeline.py index d5724244e..408a42225 100644 --- a/griptape/structures/pipeline.py +++ b/griptape/structures/pipeline.py @@ -46,12 +46,7 @@ def try_run(self, *args) -> Pipeline: self.__run_from_task(self.input_task) if self.conversation_memory and self.output is not None: - if isinstance(self.input_task.input, tuple): - input_text = self.input_task.input[0].to_text() - else: - input_text = self.input_task.input.to_text() - - run = Run(input=input_text, output=self.output.to_text()) + run = Run(input=self.input_task.input, output=self.output) self.conversation_memory.add_run(run) @@ -74,7 +69,7 @@ def __run_from_task(self, task: Optional[BaseTask]) -> None: if task is None: return else: - if isinstance(task.execute(), ErrorArtifact): + if isinstance(task.execute(), ErrorArtifact) and self.fail_fast: return else: self.__run_from_task(next(iter(task.children), None)) diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 78dd69633..c7b779590 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -1,19 +1,24 @@ from __future__ import annotations - import logging import uuid from abc import ABC, abstractmethod from logging import Logger from typing import TYPE_CHECKING, Any, Optional - from attrs import Factory, define, field from rich.logging import RichHandler - from griptape.artifacts import BlobArtifact, TextArtifact, BaseArtifact from griptape.config import BaseStructureConfig, OpenAiStructureConfig, StructureConfig from griptape.drivers import BaseEmbeddingDriver, BasePromptDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.drivers.vector.local_vector_store_driver import LocalVectorStoreDriver -from griptape.engines import CsvExtractionEngine, JsonExtractionEngine, PromptSummaryEngine, VectorQueryEngine +from griptape.engines import CsvExtractionEngine, JsonExtractionEngine, PromptSummaryEngine +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import ( + VectorStoreRetrievalRagModule, + RulesetsBeforeResponseRagModule, + PromptResponseRagModule, + MetadataBeforeResponseRagModule, +) +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.events import BaseEvent, EventListener from griptape.events.finish_structure_run_event import FinishStructureRunEvent from griptape.events.start_structure_run_event import StartStructureRunEvent @@ -52,10 +57,12 @@ class Structure(ABC): ), kw_only=True, ) - task_memory: Optional[TaskMemory] = field( + rag_engine: RagEngine = field(default=Factory(lambda self: self.default_rag_engine, takes_self=True), kw_only=True) + task_memory: TaskMemory = field( default=Factory(lambda self: self.default_task_memory, takes_self=True), kw_only=True ) meta_memory: MetaMemory = field(default=Factory(lambda: MetaMemory()), kw_only=True) + fail_fast: bool = field(default=True, kw_only=True) _execution_args: tuple = () _logger: Optional[Logger] = None @@ -140,15 +147,9 @@ def default_config(self) -> BaseStructureConfig: if self.prompt_driver is not None or self.embedding_driver is not None or self.stream is not None: config = StructureConfig() - if self.prompt_driver is None: - prompt_driver = OpenAiChatPromptDriver(model="gpt-4o") - else: - prompt_driver = self.prompt_driver + prompt_driver = OpenAiChatPromptDriver(model="gpt-4o") if self.prompt_driver is None else self.prompt_driver - if self.embedding_driver is None: - embedding_driver = OpenAiEmbeddingDriver() - else: - embedding_driver = self.embedding_driver + embedding_driver = OpenAiEmbeddingDriver() if self.embedding_driver is None else self.embedding_driver if self.stream is not None: prompt_driver.stream = self.stream @@ -163,14 +164,29 @@ def default_config(self) -> BaseStructureConfig: return config + @property + def default_rag_engine(self) -> RagEngine: + return RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[VectorStoreRetrievalRagModule(vector_store_driver=self.config.vector_store_driver)] + ), + response_stage=ResponseRagStage( + before_response_modules=[ + RulesetsBeforeResponseRagModule(rulesets=self.rulesets), + MetadataBeforeResponseRagModule(), + ], + response_module=PromptResponseRagModule(prompt_driver=self.config.prompt_driver), + ), + ) + @property def default_task_memory(self) -> TaskMemory: return TaskMemory( artifact_storages={ TextArtifact: TextArtifactStorage( - query_engine=VectorQueryEngine( - prompt_driver=self.config.prompt_driver, vector_store_driver=self.config.vector_store_driver - ), + rag_engine=self.rag_engine, + retrieval_rag_module_name="VectorStoreRetrievalRagModule", + vector_store_driver=self.config.vector_store_driver, summary_engine=PromptSummaryEngine(prompt_driver=self.config.prompt_driver), csv_extraction_engine=CsvExtractionEngine(prompt_driver=self.config.prompt_driver), json_extraction_engine=JsonExtractionEngine(prompt_driver=self.config.prompt_driver), diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 6552fba89..f7bc2e893 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -1,7 +1,7 @@ from __future__ import annotations import concurrent.futures as futures from graphlib import TopologicalSorter -from typing import Any, Optional +from typing import Any, Optional, Callable from attrs import define, field, Factory from griptape.artifacts import ErrorArtifact from griptape.structures import Structure @@ -11,7 +11,9 @@ @define class Workflow(Structure): - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) @property def output_task(self) -> Optional[BaseTask]: @@ -85,9 +87,13 @@ def insert_task( if task.id not in parent_task.child_ids: parent_task.child_ids.append(task.id) - parent_index = self.tasks.index(parent_task) - if parent_index > last_parent_index: - last_parent_index = parent_index + try: + parent_index = self.tasks.index(parent_task) + except ValueError as exc: + raise ValueError(f"Parent task {parent_task.id} not found in workflow.") from exc + else: + if parent_index > last_parent_index: + last_parent_index = parent_index # Insert the new task once, just after the last parent task self.tasks.insert(last_parent_index + 1, task) @@ -103,23 +109,18 @@ def try_run(self, *args) -> Workflow: for task in ordered_tasks: if task.can_execute(): - future = self.futures_executor.submit(task.execute) + future = self.futures_executor_fn().submit(task.execute) futures_list[future] = task # Wait for all tasks to complete for future in futures.as_completed(futures_list): - if isinstance(future.result(), ErrorArtifact): + if isinstance(future.result(), ErrorArtifact) and self.fail_fast: exit_loop = True break if self.conversation_memory and self.output is not None: - if isinstance(self.input_task.input, tuple): - input_text = self.input_task.input[0].to_text() - else: - input_text = self.input_task.input.to_text() - - run = Run(input=input_text, output=self.output_task.output.to_text()) + run = Run(input=self.input_task.input, output=self.output) self.conversation_memory.add_run(run) diff --git a/griptape/tasks/__init__.py b/griptape/tasks/__init__.py index 2c282adff..764d1669a 100644 --- a/griptape/tasks/__init__.py +++ b/griptape/tasks/__init__.py @@ -6,7 +6,7 @@ from .toolkit_task import ToolkitTask from .text_summary_task import TextSummaryTask from .tool_task import ToolTask -from .text_query_task import TextQueryTask +from .rag_task import RagTask from .extraction_task import ExtractionTask from .csv_extraction_task import CsvExtractionTask from .json_extraction_task import JsonExtractionTask @@ -31,7 +31,7 @@ "ToolkitTask", "TextSummaryTask", "ToolTask", - "TextQueryTask", + "RagTask", "ExtractionTask", "CsvExtractionTask", "JsonExtractionTask", diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index 1546a825d..c835f2b84 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -112,16 +112,14 @@ def run(self) -> BaseArtifact: self.structure.logger.error(f"Subtask {self.id}\n{e}", exc_info=True) self.output = ErrorArtifact(str(e), exception=e) - finally: - if self.output is not None: - return self.output - else: - return ErrorArtifact("no tool output") + if self.output is not None: + return self.output + else: + return ErrorArtifact("no tool output") def execute_actions(self, actions: list[Action]) -> list[tuple[str, BaseArtifact]]: - results = utils.execute_futures_dict( - {a.tag: self.futures_executor.submit(self.execute_action, a) for a in actions} - ) + with self.futures_executor_fn() as executor: + results = utils.execute_futures_dict({a.tag: executor.submit(self.execute_action, a) for a in actions}) return [r for r in results.values()] @@ -235,9 +233,8 @@ def __parse_actions(self, actions_matches: list[str]) -> None: tag=action_tag, name=action_name, path=action_path, input=action_input, tool=tool ) - if new_action.tool: - if new_action.input: - self.__validate_action(new_action) + if new_action.tool and new_action.input: + self.__validate_action(new_action) # Don't forget to add it to the subtask actions list! self.actions.append(new_action) diff --git a/griptape/tasks/base_task.py b/griptape/tasks/base_task.py index 8a45cb14e..9aa891e18 100644 --- a/griptape/tasks/base_task.py +++ b/griptape/tasks/base_task.py @@ -4,7 +4,7 @@ from abc import ABC, abstractmethod from concurrent import futures from enum import Enum -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any, Optional, Callable from attrs import define, field, Factory @@ -33,7 +33,9 @@ class State(Enum): output: Optional[BaseArtifact] = field(default=None, init=False) structure: Optional[Structure] = field(default=None, init=False) context: dict[str, Any] = field(factory=dict, kw_only=True) - futures_executor: futures.Executor = field(default=Factory(lambda: futures.ThreadPoolExecutor()), kw_only=True) + futures_executor_fn: Callable[[], futures.Executor] = field( + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + ) @property @abstractmethod @@ -142,7 +144,7 @@ def execute(self) -> Optional[BaseArtifact]: finally: self.state = BaseTask.State.FINISHED - return self.output + return self.output def can_execute(self) -> bool: return self.state == BaseTask.State.PENDING and all(parent.is_finished() for parent in self.parents) diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index 694a5050d..955855e3d 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -1,10 +1,15 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Callable -from attrs import define, field, Factory -from griptape.utils import PromptStack -from griptape.utils import J2 -from griptape.tasks import BaseTextInputTask + +from typing import TYPE_CHECKING, Callable, Optional + +from attrs import Factory, define, field + from griptape.artifacts import BaseArtifact +from griptape.common import PromptStack +from griptape.tasks import BaseTask +from griptape.utils import J2 +from griptape.artifacts import TextArtifact, ListArtifact +from griptape.mixins import RuleMixin if TYPE_CHECKING: from griptape.drivers import BasePromptDriver @@ -12,11 +17,23 @@ @define -class PromptTask(BaseTextInputTask): +class PromptTask(RuleMixin, BaseTask): _prompt_driver: Optional[BasePromptDriver] = field(default=None, kw_only=True, alias="prompt_driver") generate_system_template: Callable[[PromptTask], str] = field( default=Factory(lambda self: self.default_system_template_generator, takes_self=True), kw_only=True ) + _input: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact] = field( + default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value=""), + alias="input", + ) + + @property + def input(self) -> BaseArtifact: + return self._process_task_input(self._input) + + @input.setter + def input(self, value: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact]) -> None: + self._input = value output: Optional[BaseArtifact] = field(default=None, init=False) @@ -25,12 +42,12 @@ def prompt_stack(self) -> PromptStack: stack = PromptStack() memory = self.structure.conversation_memory - stack.add_system_input(self.generate_system_template(self)) + stack.add_system_message(self.generate_system_template(self)) - stack.add_user_input(self.input.to_text()) + stack.add_user_message(self.input) if self.output: - stack.add_assistant_input(self.output.to_text()) + stack.add_assistant_message(self.output) if memory: # inserting at index 1 to place memory right after system prompt @@ -59,7 +76,33 @@ def default_system_template_generator(self, _: PromptTask) -> str: rulesets=J2("rulesets/rulesets.j2").render(rulesets=self.all_rulesets) ) - def run(self) -> BaseArtifact: - self.output = self.prompt_driver.run(self.prompt_stack) + def before_run(self) -> None: + super().before_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nInput: {self.input.to_text()}") - return self.output + def after_run(self) -> None: + super().after_run() + + self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nOutput: {self.output.to_text()}") + + def run(self) -> BaseArtifact: + message = self.prompt_driver.run(self.prompt_stack) + + return message.to_artifact() + + def _process_task_input( + self, task_input: str | tuple | list | BaseArtifact | Callable[[BaseTask], BaseArtifact] + ) -> BaseArtifact: + if isinstance(task_input, TextArtifact): + task_input.value = J2().render_from_string(task_input.value, **self.full_context) + + return task_input + elif isinstance(task_input, Callable): + return self._process_task_input(task_input(self)) + elif isinstance(task_input, BaseArtifact): + return task_input + elif isinstance(task_input, (list, tuple)): + return ListArtifact([self._process_task_input(elem) for elem in task_input]) + else: + return self._process_task_input(TextArtifact(task_input)) diff --git a/griptape/tasks/rag_task.py b/griptape/tasks/rag_task.py new file mode 100644 index 000000000..e85c8f28a --- /dev/null +++ b/griptape/tasks/rag_task.py @@ -0,0 +1,31 @@ +from __future__ import annotations +from attrs import define, field +from griptape.artifacts import ErrorArtifact, BaseArtifact +from griptape.engines.rag import RagEngine +from griptape.tasks import BaseTextInputTask + + +@define +class RagTask(BaseTextInputTask): + _rag_engine: RagEngine = field(kw_only=True, default=None, alias="rag_engine") + + @property + def rag_engine(self) -> RagEngine: + if self._rag_engine is None: + if self.structure is not None: + self._rag_engine = self.structure.rag_engine + else: + raise ValueError("rag_engine is not set.") + return self._rag_engine + + @rag_engine.setter + def rag_engine(self, value: RagEngine) -> None: + self._rag_engine = value + + def run(self) -> BaseArtifact: + result = self.rag_engine.process_query(self.input.to_text()).output + + if result is None: + return ErrorArtifact("empty output") + else: + return result diff --git a/griptape/tasks/text_query_task.py b/griptape/tasks/text_query_task.py deleted file mode 100644 index f35161c17..000000000 --- a/griptape/tasks/text_query_task.py +++ /dev/null @@ -1,35 +0,0 @@ -from attrs import define, field, Factory -from typing import Optional -from griptape.artifacts import TextArtifact -from griptape.engines import BaseQueryEngine, VectorQueryEngine -from griptape.loaders import TextLoader -from griptape.tasks import BaseTextInputTask - - -@define -class TextQueryTask(BaseTextInputTask): - _query_engine: BaseQueryEngine = field(kw_only=True, default=None, alias="query_engine") - loader: TextLoader = field(default=Factory(lambda: TextLoader()), kw_only=True) - namespace: Optional[str] = field(default=None, kw_only=True) - top_n: Optional[int] = field(default=None, kw_only=True) - - @property - def query_engine(self) -> BaseQueryEngine: - if self._query_engine is None: - if self.structure is not None: - self._query_engine = VectorQueryEngine( - prompt_driver=self.structure.config.prompt_driver, - vector_store_driver=self.structure.config.vector_store_driver, - ) - else: - raise ValueError("Query Engine is not set.") - return self._query_engine - - @query_engine.setter - def query_engine(self, value: BaseQueryEngine) -> None: - self._query_engine = value - - def run(self) -> TextArtifact: - return self.query_engine.query( - self.input.to_text(), namespace=self.namespace, rulesets=self.all_rulesets, top_n=self.top_n - ) diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index 61b19b5d3..cfad9f49f 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -10,7 +10,7 @@ from griptape.tasks import ActionsSubtask from griptape.tasks import PromptTask from griptape.utils import J2 -from griptape.utils import PromptStack +from griptape.common import PromptStack if TYPE_CHECKING: from griptape.tools import BaseTool @@ -65,16 +65,16 @@ def prompt_stack(self) -> PromptStack: stack = PromptStack() memory = self.structure.conversation_memory - stack.add_system_input(self.generate_system_template(self)) + stack.add_system_message(self.generate_system_template(self)) - stack.add_user_input(self.input.to_text()) + stack.add_user_message(self.input) if self.output: - stack.add_assistant_input(self.output.to_text()) + stack.add_assistant_message(self.output.to_text()) else: for s in self.subtasks: - stack.add_assistant_input(self.generate_assistant_subtask_template(s)) - stack.add_user_input(self.generate_user_subtask_template(s)) + stack.add_assistant_message(self.generate_assistant_subtask_template(s)) + stack.add_user_message(self.generate_user_subtask_template(s)) if memory: # inserting at index 1 to place memory right after system prompt diff --git a/griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 b/griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 new file mode 100644 index 000000000..0dcf60fd4 --- /dev/null +++ b/griptape/templates/engines/rag/modules/response/footnote_prompt/system.j2 @@ -0,0 +1,37 @@ +You are an expert Q&A system. Always answer the question using the provided context information, and not prior knowledge. Always be truthful. Don't make up facts. +{% if before_system_prompt %} +{{ before_system_prompt }} + +{% endif %} +Use the following list of excerpts to respond. If there are no excerpts available or excerpts don't have relevant information respond with "I could not find an answer." + +When responding to a question, always reference facts from excerpts whenever possible. Some excerpts might have references associated with them. When referencing facts from excerpts always add a footnote number in square brackets after that fact. At the end of your response compile a list of footnotes. Always include a reference title and other available reference information. Make sure footnotes are unique and have no duplicates. +{% if references|length > 0 %} + +## References + +{% for reference in references %} +{{ reference }} +{% endfor %} +{% endif %} +{% if text_chunk_artifacts|length > 0 %} + +## Excerpts + +{% for artifact in text_chunk_artifacts %} +{% if artifact.reference %} +Excerpt (Reference ID: {{ artifact.reference.id }}): """ +{{ artifact.to_text() }} +{% else %} +Excerpt: """ +{{ artifact.to_text() }} +{% endif %} +""" +{% endfor %} +{% if after_system_prompt %} + +{{ after_system_prompt }} +{% endif %} +{% else %} +No excerpt available. +{% endif %} \ No newline at end of file diff --git a/griptape/templates/engines/rag/modules/response/metadata/system.j2 b/griptape/templates/engines/rag/modules/response/metadata/system.j2 new file mode 100644 index 000000000..601fc7a13 --- /dev/null +++ b/griptape/templates/engines/rag/modules/response/metadata/system.j2 @@ -0,0 +1,5 @@ +{% if metadata %} +Metadata: """ +{{ metadata }} +""" +{% endif %} \ No newline at end of file diff --git a/griptape/templates/engines/rag/modules/response/prompt/system.j2 b/griptape/templates/engines/rag/modules/response/prompt/system.j2 new file mode 100644 index 000000000..1fa9d8c12 --- /dev/null +++ b/griptape/templates/engines/rag/modules/response/prompt/system.j2 @@ -0,0 +1,22 @@ +You are an expert Q&A system. Always answer the question using the provided context information, and not prior knowledge. Always be truthful. Don't make up facts. You can answer questions by searching through text chunks. +{% if before_system_prompt %} +{{ before_system_prompt }} + +{% endif %} +Use the following list of text chunks to respond. If there are no text chunks available or text chunks don't have relevant information respond with "I could not find an answer." + +{% if text_chunks and text_chunks|length > 0 %} +## Text Chunks +{% for chunk in text_chunks %} + +Text chunk: """ +{{ chunk }} +""" +{% endfor %} +{% if after_system_prompt %} + +{{ after_system_prompt }} +{% endif %} +{% else %} +No text chunks available. +{% endif %} \ No newline at end of file diff --git a/griptape/tokenizers/amazon_bedrock_tokenizer.py b/griptape/tokenizers/amazon_bedrock_tokenizer.py index 670b5739a..951802d59 100644 --- a/griptape/tokenizers/amazon_bedrock_tokenizer.py +++ b/griptape/tokenizers/amazon_bedrock_tokenizer.py @@ -1,4 +1,5 @@ from __future__ import annotations + from attrs import define, field from griptape.tokenizers.base_tokenizer import BaseTokenizer diff --git a/griptape/tokenizers/base_tokenizer.py b/griptape/tokenizers/base_tokenizer.py index 474ccbaa5..212e40058 100644 --- a/griptape/tokenizers/base_tokenizer.py +++ b/griptape/tokenizers/base_tokenizer.py @@ -1,6 +1,6 @@ from __future__ import annotations import logging -from abc import ABC +from abc import ABC, abstractmethod from attrs import define, field, Factory @@ -40,6 +40,7 @@ def count_output_tokens_left(self, text: str) -> int: else: return 0 + @abstractmethod def count_tokens(self, text: str) -> int: ... def _default_max_input_tokens(self) -> int: diff --git a/griptape/tokenizers/huggingface_tokenizer.py b/griptape/tokenizers/huggingface_tokenizer.py index a8312567d..fdebd23da 100644 --- a/griptape/tokenizers/huggingface_tokenizer.py +++ b/griptape/tokenizers/huggingface_tokenizer.py @@ -1,4 +1,5 @@ from __future__ import annotations + from typing import TYPE_CHECKING from attrs import define, field, Factory from griptape.utils import import_optional_dependency diff --git a/griptape/tokenizers/openai_tokenizer.py b/griptape/tokenizers/openai_tokenizer.py index 39a2a033e..a58ec5ce5 100644 --- a/griptape/tokenizers/openai_tokenizer.py +++ b/griptape/tokenizers/openai_tokenizer.py @@ -1,8 +1,11 @@ from __future__ import annotations + import logging -from attrs import define, field, Factory -import tiktoken from typing import Optional + +import tiktoken +from attrs import Factory, define, field + from griptape.tokenizers import BaseTokenizer diff --git a/griptape/tokenizers/voyageai_tokenizer.py b/griptape/tokenizers/voyageai_tokenizer.py index d8fb5adf1..649f6e0cc 100644 --- a/griptape/tokenizers/voyageai_tokenizer.py +++ b/griptape/tokenizers/voyageai_tokenizer.py @@ -1,8 +1,11 @@ from __future__ import annotations -from attrs import define, field, Factory + from typing import TYPE_CHECKING, Optional -from griptape.utils import import_optional_dependency + +from attrs import Factory, define, field + from griptape.tokenizers import BaseTokenizer +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from voyageai import Client diff --git a/griptape/tools/__init__.py b/griptape/tools/__init__.py index 1c152c95a..0bacdb303 100644 --- a/griptape/tools/__init__.py +++ b/griptape/tools/__init__.py @@ -26,6 +26,7 @@ from .griptape_cloud_knowledge_base_client.tool import GriptapeCloudKnowledgeBaseClient from .structure_run_client.tool import StructureRunClient from .image_query_client.tool import ImageQueryClient +from .rag_client.tool import RagClient from .text_to_speech_client.tool import TextToSpeechClient from .audio_transcription_client.tool import AudioTranscriptionClient @@ -58,6 +59,7 @@ "GriptapeCloudKnowledgeBaseClient", "StructureRunClient", "ImageQueryClient", + "RagClient", "TextToSpeechClient", "AudioTranscriptionClient", ] diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 8a0a924ac..03aaf22b5 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -35,7 +35,7 @@ class BaseTool(ActivityMixin, ABC): MANIFEST_FILE = "manifest.yml" REQUIREMENTS_FILE = "requirements.txt" - name: str = field(default=Factory(lambda self: self.class_name, takes_self=True), kw_only=True) + name: str = field(default=Factory(lambda self: self.__class__.__name__, takes_self=True), kw_only=True) input_memory: Optional[list[TaskMemory]] = field(default=None, kw_only=True) output_memory: Optional[dict[str, list[TaskMemory]]] = field(default=None, kw_only=True) install_dependencies_on_init: bool = field(default=True, kw_only=True) @@ -61,10 +61,6 @@ def validate_output_memory(self, _, output_memory: dict[str, Optional[list[TaskM if len(output_memory_names) > len(set(output_memory_names)): raise ValueError(f"memory names have to be unique in activity '{activity_name}' output") - @property - def class_name(self): - return self.__class__.__name__ - @property def manifest_path(self) -> str: return os.path.join(self.abs_dir_path, self.MANIFEST_FILE) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 6fed6e618..7c94cda5d 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -31,7 +31,7 @@ def query(self, params: dict) -> TextArtifact | ErrorArtifact: from requests import post, exceptions query = params["values"]["query"] - url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") + url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/search") try: response = post(url, json={"query": query}, headers=self.headers) diff --git a/griptape/tools/prompt_image_generation_client/tool.py b/griptape/tools/prompt_image_generation_client/tool.py index 50020a1ea..6f4ce0e1f 100644 --- a/griptape/tools/prompt_image_generation_client/tool.py +++ b/griptape/tools/prompt_image_generation_client/tool.py @@ -30,20 +30,15 @@ class PromptImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): Literal( "prompts", description="A detailed list of features and descriptions to include in the generated image.", - ): list[str], - Literal( - "negative_prompts", - description="A detailed list of features and descriptions to avoid in the generated image.", - ): list[str], + ): list[str] } ), } ) def generate_image(self, params: dict[str, dict[str, list[str]]]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] - negative_prompts = params["values"]["negative_prompts"] - output_artifact = self.engine.run(prompts=prompts, negative_prompts=negative_prompts) + output_artifact = self.engine.run(prompts=prompts) if self.output_dir or self.output_file: self._write_to_file(output_artifact) diff --git a/griptape/tools/rag_client/__init__.py b/griptape/tools/rag_client/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/tools/rag_client/manifest.yml b/griptape/tools/rag_client/manifest.yml new file mode 100644 index 000000000..86998feb4 --- /dev/null +++ b/griptape/tools/rag_client/manifest.yml @@ -0,0 +1,5 @@ +version: "v1" +name: RAG Client +description: Tool for querying RAG engines +contact_email: hello@griptape.ai +legal_info_url: https://www.griptape.ai/legal \ No newline at end of file diff --git a/griptape/tools/rag_client/requirements.txt b/griptape/tools/rag_client/requirements.txt new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/tools/rag_client/tool.py b/griptape/tools/rag_client/tool.py new file mode 100644 index 000000000..94422cc15 --- /dev/null +++ b/griptape/tools/rag_client/tool.py @@ -0,0 +1,38 @@ +from __future__ import annotations +from attrs import define, field +from schema import Schema, Literal +from griptape.artifacts import ErrorArtifact, BaseArtifact +from griptape.engines.rag import RagEngine +from griptape.tools import BaseTool +from griptape.utils.decorators import activity + + +@define(kw_only=True) +class RagClient(BaseTool): + """ + Attributes: + description: LLM-friendly RAG engine description. + rag_engine: `RagEngine`. + """ + + description: str = field() + rag_engine: RagEngine = field() + + @activity( + config={ + "description": "{{ _self.description }}", + "schema": Schema({Literal("query", description="A natural language search query"): str}), + } + ) + def search(self, params: dict) -> BaseArtifact: + query = params["values"]["query"] + + try: + result = self.rag_engine.process_query(query) + + if result.output is None: + return ErrorArtifact("query output is empty") + else: + return result.output + except Exception as e: + return ErrorArtifact(f"error querying: {e}") diff --git a/griptape/tools/task_memory_client/tool.py b/griptape/tools/task_memory_client/tool.py index b60c0acc0..ce89da22e 100644 --- a/griptape/tools/task_memory_client/tool.py +++ b/griptape/tools/task_memory_client/tool.py @@ -1,7 +1,7 @@ from __future__ import annotations from attrs import define from schema import Schema, Literal -from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact +from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact, BaseArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity @@ -39,7 +39,7 @@ def summarize(self, params: dict) -> TextArtifact | InfoArtifact | ErrorArtifact ), } ) - def query(self, params: dict) -> TextArtifact | InfoArtifact | ErrorArtifact: + def query(self, params: dict) -> BaseArtifact: memory = self.find_input_memory(params["values"]["memory_name"]) artifact_namespace = params["values"]["artifact_namespace"] query = params["values"]["query"] diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index f2dc785b0..8d4e73022 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -1,32 +1,36 @@ -from typing import Optional -from griptape.engines import VectorQueryEngine +from __future__ import annotations +from typing import Callable, Any +from attrs import define, field, Factory from schema import Schema, Literal -from attrs import define, field -from griptape.artifacts import BaseArtifact, ErrorArtifact +from griptape.artifacts import ErrorArtifact, BaseArtifact +from griptape.artifacts import ListArtifact +from griptape.drivers import BaseVectorStoreDriver from griptape.tools import BaseTool from griptape.utils.decorators import activity -@define +@define(kw_only=True) class VectorStoreClient(BaseTool): """ Attributes: description: LLM-friendly vector DB description. - namespace: Vector storage namespace. - query_engine: `BaseQueryEngine`. - top_n: Max number of results returned for the query engine query. + vector_store_driver: `BaseVectorStoreDriver`. + query_params: Optional dictionary of vector store driver query parameters. + process_query_output_fn: Optional lambda for processing vector store driver query output `Entry`s. """ DEFAULT_TOP_N = 5 - description: str = field(kw_only=True) - query_engine: VectorQueryEngine = field(kw_only=True) - top_n: int = field(default=DEFAULT_TOP_N, kw_only=True) - namespace: Optional[str] = field(default=None, kw_only=True) + description: str = field() + vector_store_driver: BaseVectorStoreDriver = field() + query_params: dict[str, Any] = field(factory=dict) + process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], BaseArtifact] = field( + default=Factory(lambda: lambda es: ListArtifact([e.to_artifact() for e in es])) + ) @activity( config={ - "description": "Can be used to search a vector database with the following description: {{ _self.description }}", + "description": "Can be used to search a database with the following description: {{ _self.description }}", "schema": Schema( { Literal( @@ -40,6 +44,6 @@ def search(self, params: dict) -> BaseArtifact: query = params["values"]["query"] try: - return self.query_engine.query(query, top_n=self.top_n, namespace=self.namespace) + return self.process_query_output_fn(self.vector_store_driver.query(query, **self.query_params)) except Exception as e: return ErrorArtifact(f"error querying vector store: {e}") diff --git a/griptape/tools/web_search/tool.py b/griptape/tools/web_search/tool.py index acc358342..e5dc9add7 100644 --- a/griptape/tools/web_search/tool.py +++ b/griptape/tools/web_search/tool.py @@ -1,20 +1,15 @@ from __future__ import annotations from attrs import define, field -from griptape.artifacts import TextArtifact, ErrorArtifact, ListArtifact +from griptape.artifacts import ErrorArtifact, ListArtifact from schema import Schema, Literal from griptape.tools import BaseTool from griptape.utils.decorators import activity -import requests -import json +from griptape.drivers import BaseWebSearchDriver @define class WebSearch(BaseTool): - results_count: int = field(default=5, kw_only=True) - google_api_lang: str = field(default="lang_en", kw_only=True) - google_api_key: str = field(kw_only=True) - google_api_search_id: str = field(kw_only=True) - google_api_country: str = field(default="us", kw_only=True) + web_search_driver: BaseWebSearchDriver = field(default=None, kw_only=True) @activity( config={ @@ -33,31 +28,6 @@ def search(self, props: dict) -> ListArtifact | ErrorArtifact: query = props["values"]["query"] try: - return ListArtifact([TextArtifact(json.dumps(result)) for result in self._search_google(query)]) + return self.web_search_driver.search(query) except Exception as e: - return ErrorArtifact(f"error searching Google: {e}") - - def _search_google(self, query: str) -> list[dict]: - url = ( - f"https://www.googleapis.com/customsearch/v1?" - f"key={self.google_api_key}&" - f"cx={self.google_api_search_id}&" - f"q={query}&" - f"start=0&" - f"lr={self.google_api_lang}&" - f"num={self.results_count}&" - f"gl={self.google_api_country}" - ) - response = requests.get(url) - - if response.status_code == 200: - data = response.json() - - links = [{"url": r["link"], "title": r["title"], "description": r["snippet"]} for r in data["items"]] - - return links - else: - raise Exception( - f"Google Search API returned an error with status code " - f"{response.status_code} and reason '{response.reason}'" - ) + return ErrorArtifact(f"Error searching '{query}' with {self.web_search_driver.__class__.__name__}: {e}") diff --git a/griptape/utils/__init__.py b/griptape/utils/__init__.py index daac63f4e..ceb19547e 100644 --- a/griptape/utils/__init__.py +++ b/griptape/utils/__init__.py @@ -6,8 +6,8 @@ from .command_runner import CommandRunner from .chat import Chat from .futures import execute_futures_dict +from .futures import execute_futures_list from .token_counter import TokenCounter -from .prompt_stack import PromptStack from .dict_utils import remove_null_values_in_dict_recursively, dict_merge from .file_utils import load_file, load_files from .hash import str_to_hash @@ -17,6 +17,7 @@ from .load_artifact_from_memory import load_artifact_from_memory from .deprecation import deprecation_warn from .structure_visualizer import StructureVisualizer +from .reference_utils import references_from_artifacts def minify_json(value: str) -> str: @@ -35,8 +36,8 @@ def minify_json(value: str) -> str: "import_optional_dependency", "is_dependency_installed", "execute_futures_dict", + "execute_futures_list", "TokenCounter", - "PromptStack", "remove_null_values_in_dict_recursively", "dict_merge", "Stream", @@ -45,4 +46,5 @@ def minify_json(value: str) -> str: "load_file", "load_files", "StructureVisualizer", + "references_from_artifacts", ] diff --git a/griptape/utils/chat.py b/griptape/utils/chat.py index 12653ce9e..f78d311f9 100644 --- a/griptape/utils/chat.py +++ b/griptape/utils/chat.py @@ -1,6 +1,9 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Callable + +from typing import TYPE_CHECKING, Callable, Optional + from attrs import Factory, define, field + from griptape.utils.stream import Stream if TYPE_CHECKING: @@ -22,9 +25,9 @@ class Chat: def default_output_fn(self, text: str) -> None: if self.structure.config.prompt_driver.stream: - print(text, end="", flush=True) + print(text, end="", flush=True) # noqa T201 else: - print(text) + print(text) # noqa T201 def start(self) -> None: if self.intro_text: diff --git a/griptape/utils/conversation.py b/griptape/utils/conversation.py index 2d87563ae..ae05e8b99 100644 --- a/griptape/utils/conversation.py +++ b/griptape/utils/conversation.py @@ -22,8 +22,8 @@ def lines(self) -> list[str]: def prompt_stack(self) -> list[str]: lines = [] - for stack in self.memory.to_prompt_stack().inputs: - lines.append(f"{stack.role}: {stack.content}") + for stack in self.memory.to_prompt_stack().messages: + lines.append(f"{stack.role}: {stack.to_text()}") return lines diff --git a/griptape/utils/dict_utils.py b/griptape/utils/dict_utils.py index 64a91d68b..a396bf7d1 100644 --- a/griptape/utils/dict_utils.py +++ b/griptape/utils/dict_utils.py @@ -1,3 +1,6 @@ +from typing import Optional + + def remove_null_values_in_dict_recursively(d: dict) -> dict: if isinstance(d, dict): return {k: remove_null_values_in_dict_recursively(v) for k, v in d.items() if v is not None} @@ -5,7 +8,7 @@ def remove_null_values_in_dict_recursively(d: dict) -> dict: return d -def dict_merge(dct: dict, merge_dct: dict, add_keys: bool = True) -> dict: +def dict_merge(dct: Optional[dict], merge_dct: Optional[dict], add_keys: bool = True) -> dict: """Recursive dict merge. Inspired by :meth:``dict.update()``, instead of updating only top-level keys, dict_merge recurses down into dicts nested to an arbitrary depth, updating keys. The ``merge_dct`` is merged into @@ -26,11 +29,15 @@ def dict_merge(dct: dict, merge_dct: dict, add_keys: bool = True) -> dict: Returns: dict: updated dict """ + dct = {} if dct is None else dct + merge_dct = {} if merge_dct is None else merge_dct + dct = dct.copy() + if not add_keys: merge_dct = {k: merge_dct[k] for k in set(dct).intersection(set(merge_dct))} - for key in merge_dct.keys(): + for key in merge_dct: if key in dct and isinstance(dct[key], dict): dct[key] = dict_merge(dct[key], merge_dct[key], add_keys=add_keys) else: diff --git a/griptape/utils/file_utils.py b/griptape/utils/file_utils.py index 402436a2f..ebe5ba456 100644 --- a/griptape/utils/file_utils.py +++ b/griptape/utils/file_utils.py @@ -30,6 +30,7 @@ def load_files(paths: list[str], futures_executor: Optional[futures.ThreadPoolEx if futures_executor is None: futures_executor = futures.ThreadPoolExecutor() - return utils.execute_futures_dict( - {utils.str_to_hash(str(path)): futures_executor.submit(load_file, path) for path in paths} - ) + with futures_executor as executor: + return utils.execute_futures_dict( + {utils.str_to_hash(str(path)): executor.submit(load_file, path) for path in paths} + ) diff --git a/griptape/utils/futures.py b/griptape/utils/futures.py index 55a4e5d55..d69f4ea48 100644 --- a/griptape/utils/futures.py +++ b/griptape/utils/futures.py @@ -8,3 +8,9 @@ def execute_futures_dict(fs_dict: dict[str, futures.Future[T]]) -> dict[str, T]: futures.wait(fs_dict.values(), timeout=None, return_when=futures.ALL_COMPLETED) return {key: future.result() for key, future in fs_dict.items()} + + +def execute_futures_list(fs_list: list[futures.Future[T]]) -> list[T]: + futures.wait(fs_list, timeout=None, return_when=futures.ALL_COMPLETED) + + return [future.result() for future in fs_list] diff --git a/griptape/utils/import_utils.py b/griptape/utils/import_utils.py index 5e00551f8..0de09b2d1 100644 --- a/griptape/utils/import_utils.py +++ b/griptape/utils/import_utils.py @@ -32,8 +32,8 @@ def import_optional_dependency(name: str) -> Optional[ModuleType]: ) try: module = import_module(name) - except ImportError: - raise ImportError(msg) + except ImportError as exc: + raise ImportError(msg) from exc return module diff --git a/griptape/utils/load_artifact_from_memory.py b/griptape/utils/load_artifact_from_memory.py index 6ab823130..af11b8ae8 100644 --- a/griptape/utils/load_artifact_from_memory.py +++ b/griptape/utils/load_artifact_from_memory.py @@ -14,8 +14,8 @@ def load_artifact_from_memory( try: artifact = [a for a in artifacts if a.name == artifact_name][0] - except IndexError: - raise ValueError(f"artifact {artifact_name} not found in namespace {artifact_namespace}") + except IndexError as exc: + raise ValueError(f"artifact {artifact_name} not found in namespace {artifact_namespace}") from exc if not isinstance(artifact, artifact_type): raise ValueError(f"{artifact.name} is not of type {artifact_type}") diff --git a/griptape/utils/prompt_stack.py b/griptape/utils/prompt_stack.py deleted file mode 100644 index 378f9dd1e..000000000 --- a/griptape/utils/prompt_stack.py +++ /dev/null @@ -1,48 +0,0 @@ -from __future__ import annotations -from attrs import define, field - -from griptape.mixins import SerializableMixin - - -@define -class PromptStack(SerializableMixin): - GENERIC_ROLE = "generic" - USER_ROLE = "user" - ASSISTANT_ROLE = "assistant" - SYSTEM_ROLE = "system" - - @define - class Input(SerializableMixin): - content: str = field(metadata={"serializable": True}) - role: str = field(metadata={"serializable": True}) - - def is_generic(self) -> bool: - return self.role == PromptStack.GENERIC_ROLE - - def is_system(self) -> bool: - return self.role == PromptStack.SYSTEM_ROLE - - def is_user(self) -> bool: - return self.role == PromptStack.USER_ROLE - - def is_assistant(self) -> bool: - return self.role == PromptStack.ASSISTANT_ROLE - - inputs: list[Input] = field(factory=list, kw_only=True, metadata={"serializable": True}) - - def add_input(self, content: str, role: str) -> Input: - self.inputs.append(self.Input(content=content, role=role)) - - return self.inputs[-1] - - def add_generic_input(self, content: str) -> Input: - return self.add_input(content, self.GENERIC_ROLE) - - def add_system_input(self, content: str) -> Input: - return self.add_input(content, self.SYSTEM_ROLE) - - def add_user_input(self, content: str) -> Input: - return self.add_input(content, self.USER_ROLE) - - def add_assistant_input(self, content: str) -> Input: - return self.add_input(content, self.ASSISTANT_ROLE) diff --git a/griptape/utils/reference_utils.py b/griptape/utils/reference_utils.py new file mode 100644 index 000000000..761ee3d24 --- /dev/null +++ b/griptape/utils/reference_utils.py @@ -0,0 +1,12 @@ +from griptape.artifacts import TextArtifact +from griptape.common import Reference + + +def references_from_artifacts(artifacts: list[TextArtifact]) -> list[Reference]: + references = [] + + for a in artifacts: + if a.reference is not None and a.reference not in references: + references.append(a.reference) + + return references diff --git a/griptape/utils/structure_visualizer.py b/griptape/utils/structure_visualizer.py index ede282761..2a159a282 100644 --- a/griptape/utils/structure_visualizer.py +++ b/griptape/utils/structure_visualizer.py @@ -1,5 +1,6 @@ from __future__ import annotations import base64 +import hashlib from attrs import define, field from typing import TYPE_CHECKING @@ -32,11 +33,14 @@ def to_url(self) -> str: base64_string = base64.b64encode(graph_bytes).decode("utf-8") url = f"https://mermaid.ink/svg/{base64_string}" - return url def __render_task(self, task: BaseTask) -> str: if task.children: - return f'{task.id}--> {" & ".join([child.id for child in task.children])};' + children = " & ".join([f"{self.__get_id(child.id)}({child.id})" for child in task.children]) + return f"{self.__get_id(task.id)}({task.id})--> {children};" else: - return f"{task.id};" + return f"{self.__get_id(task.id)}({task.id});" + + def __get_id(self, string: str) -> str: + return hashlib.md5(string.encode()).hexdigest()[:8] diff --git a/mkdocs.yml b/mkdocs.yml index 317409c55..337b75f31 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -93,7 +93,8 @@ nav: - Overview: "griptape-framework/tools/index.md" - Building Custom Tools: "griptape-tools/custom-tools/index.md" - Engines: - - Query Engines: "griptape-framework/engines/query-engines.md" + - RAG Engines: "griptape-framework/engines/rag-engines.md" + - Image Query Engines: "griptape-framework/engines/image-query-engines.md" - Extraction Engines: "griptape-framework/engines/extraction-engines.md" - Summary Engines: "griptape-framework/engines/summary-engines.md" - Image Generation Engines: "griptape-framework/engines/image-generation-engines.md" @@ -111,6 +112,7 @@ nav: - Structure Run Drivers: "griptape-framework/drivers/structure-run-drivers.md" - Text to Speech Drivers: "griptape-framework/drivers/text-to-speech-drivers.md" - Audio Transcription Drivers: "griptape-framework/drivers/audio-transcription-drivers.md" + - Web Search Drivers: "griptape-framework/drivers/web-search-drivers.md" - Data: - Overview: "griptape-framework/data/index.md" - Artifacts: "griptape-framework/data/artifacts.md" @@ -149,6 +151,7 @@ nav: - TextToSpeechClient: "griptape-tools/official-tools/text-to-speech-client.md" - AudioTranscriptionClient: "griptape-tools/official-tools/audio-transcription-client.md" - GriptapeCloudKnowledgeBaseClient: "griptape-tools/official-tools/griptape-cloud-knowledge-base-client.md" + - RagClient: "griptape-tools/official-tools/rag-client.md" - Custom Tools: - Building Custom Tools: "griptape-tools/custom-tools/index.md" - Recipes: diff --git a/poetry.lock b/poetry.lock index cb6d0ed99..da5b152d2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -757,13 +757,13 @@ files = [ [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, ] [[package]] @@ -1232,6 +1232,26 @@ files = [ {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] +[[package]] +name = "duckduckgo-search" +version = "6.1.7" +description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine." +optional = true +python-versions = ">=3.8" +files = [ + {file = "duckduckgo_search-6.1.7-py3-none-any.whl", hash = "sha256:ec7d5becb8c392c0293ff9464938c1014896e1e14725c05adc306290a636fab2"}, + {file = "duckduckgo_search-6.1.7.tar.gz", hash = "sha256:c6fd8ba17fe9cd0a4f32e5b96984e959c3da865f9c2864bfcf82bf7ff9b7e8f0"}, +] + +[package.dependencies] +click = ">=8.1.7" +orjson = ">=3.10.5" +pyreqwest-impersonate = ">=0.4.8" + +[package.extras] +dev = ["mypy (>=1.10.0)", "pytest (>=8.2.2)", "pytest-asyncio (>=0.23.7)", "ruff (>=0.4.8)"] +lxml = ["lxml (>=5.2.2)"] + [[package]] name = "elevenlabs" version = "1.1.2" @@ -1523,17 +1543,18 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "google-ai-generativelanguage" -version = "0.4.0" +version = "0.6.5" description = "Google Ai Generativelanguage API client library" optional = true python-versions = ">=3.7" files = [ - {file = "google-ai-generativelanguage-0.4.0.tar.gz", hash = "sha256:c8199066c08f74c4e91290778329bb9f357ba1ea5d6f82de2bc0d10552bf4f8c"}, - {file = "google_ai_generativelanguage-0.4.0-py3-none-any.whl", hash = "sha256:e4c425376c1ee26c78acbc49a24f735f90ebfa81bf1a06495fae509a2433232c"}, + {file = "google-ai-generativelanguage-0.6.5.tar.gz", hash = "sha256:c4089c277fa4e26722f76ab03ee3039f28be8bf1c9be282948b9583a154c6d79"}, + {file = "google_ai_generativelanguage-0.6.5-py3-none-any.whl", hash = "sha256:236875bb4a6d6ebdba2f12bd9d5e776100fd913402157a47b5e9fb80a13f25a7"}, ] [package.dependencies] -google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" proto-plus = ">=1.22.3,<2.0.0dev" protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev" @@ -1568,6 +1589,24 @@ grpc = ["grpcio (>=1.33.2,<2.0dev)", "grpcio (>=1.49.1,<2.0dev)", "grpcio-status grpcgcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"] +[[package]] +name = "google-api-python-client" +version = "2.134.0" +description = "Google API Client Library for Python" +optional = true +python-versions = ">=3.7" +files = [ + {file = "google-api-python-client-2.134.0.tar.gz", hash = "sha256:4a8f0bea651a212997cc83c0f271fc86f80ef93d1cee9d84de7dfaeef2a858b6"}, + {file = "google_api_python_client-2.134.0-py2.py3-none-any.whl", hash = "sha256:ba05d60f6239990b7994f6328f17bb154c602d31860fb553016dc9f8ce886945"}, +] + +[package.dependencies] +google-api-core = ">=1.31.5,<2.0.dev0 || >2.3.0,<3.0.0.dev0" +google-auth = ">=1.32.0,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" +google-auth-httplib2 = ">=0.2.0,<1.0.0" +httplib2 = ">=0.19.0,<1.dev0" +uritemplate = ">=3.0.1,<5" + [[package]] name = "google-auth" version = "2.29.0" @@ -1591,19 +1630,35 @@ pyopenssl = ["cryptography (>=38.0.3)", "pyopenssl (>=20.0.0)"] reauth = ["pyu2f (>=0.1.5)"] requests = ["requests (>=2.20.0,<3.0.0.dev0)"] +[[package]] +name = "google-auth-httplib2" +version = "0.2.0" +description = "Google Authentication Library: httplib2 transport" +optional = true +python-versions = "*" +files = [ + {file = "google-auth-httplib2-0.2.0.tar.gz", hash = "sha256:38aa7badf48f974f1eb9861794e9c0cb2a0511a4ec0679b1f886d108f5640e05"}, + {file = "google_auth_httplib2-0.2.0-py2.py3-none-any.whl", hash = "sha256:b65a0a2123300dd71281a7bf6e64d65a0759287df52729bdd1ae2e47dc311a3d"}, +] + +[package.dependencies] +google-auth = "*" +httplib2 = ">=0.19.0" + [[package]] name = "google-generativeai" -version = "0.4.1" +version = "0.7.0" description = "Google Generative AI High level API client library and tools." optional = true python-versions = ">=3.9" files = [ - {file = "google_generativeai-0.4.1-py3-none-any.whl", hash = "sha256:89be3c00c2e688108fccefc50f47f45fc9d37ecd53c1ade9d86b5d982919c24a"}, + {file = "google_generativeai-0.7.0-py3-none-any.whl", hash = "sha256:7be4b634afeb8b6bebde1af7271e94d2af84d2d28b5988c7ed9921733c40fe63"}, ] [package.dependencies] -google-ai-generativelanguage = "0.4.0" +google-ai-generativelanguage = "0.6.5" google-api-core = "*" +google-api-python-client = "*" google-auth = ">=2.15.0" protobuf = "*" pydantic = "*" @@ -1789,6 +1844,74 @@ googleapis-common-protos = ">=1.5.5" grpcio = ">=1.62.2" protobuf = ">=4.21.6" +[[package]] +name = "grpcio-tools" +version = "1.62.2" +description = "Protobuf code generator for gRPC" +optional = true +python-versions = ">=3.7" +files = [ + {file = "grpcio-tools-1.62.2.tar.gz", hash = "sha256:5fd5e1582b678e6b941ee5f5809340be5e0724691df5299aae8226640f94e18f"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-linux_armv7l.whl", hash = "sha256:1679b4903aed2dc5bd8cb22a452225b05dc8470a076f14fd703581efc0740cdb"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:9d41e0e47dd075c075bb8f103422968a65dd0d8dc8613288f573ae91eb1053ba"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:987e774f74296842bbffd55ea8826370f70c499e5b5f71a8cf3103838b6ee9c3"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd4eeea4b25bcb6903b82930d579027d034ba944393c4751cdefd9c49e6989"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b6746bc823958499a3cf8963cc1de00072962fb5e629f26d658882d3f4c35095"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2ed775e844566ce9ce089be9a81a8b928623b8ee5820f5e4d58c1a9d33dfc5ae"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bdc5dd3f57b5368d5d661d5d3703bcaa38bceca59d25955dff66244dbc987271"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-win32.whl", hash = "sha256:3a8d6f07e64c0c7756f4e0c4781d9d5a2b9cc9cbd28f7032a6fb8d4f847d0445"}, + {file = "grpcio_tools-1.62.2-cp310-cp310-win_amd64.whl", hash = "sha256:e33b59fb3efdddeb97ded988a871710033e8638534c826567738d3edce528752"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-linux_armv7l.whl", hash = "sha256:472505d030135d73afe4143b0873efe0dcb385bd6d847553b4f3afe07679af00"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:ec674b4440ef4311ac1245a709e87b36aca493ddc6850eebe0b278d1f2b6e7d1"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:184b4174d4bd82089d706e8223e46c42390a6ebac191073b9772abc77308f9fa"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c195d74fe98541178ece7a50dad2197d43991e0f77372b9a88da438be2486f12"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a34d97c62e61bfe9e6cff0410fe144ac8cca2fc979ad0be46b7edf026339d161"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb8453ae83a1db2452b7fe0f4b78e4a8dd32be0f2b2b73591ae620d4d784d3d"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4f989e5cebead3ae92c6abf6bf7b19949e1563a776aea896ac5933f143f0c45d"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-win32.whl", hash = "sha256:c48fabe40b9170f4e3d7dd2c252e4f1ff395dc24e49ac15fc724b1b6f11724da"}, + {file = "grpcio_tools-1.62.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c616d0ad872e3780693fce6a3ac8ef00fc0963e6d7815ce9dcfae68ba0fc287"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-linux_armv7l.whl", hash = "sha256:10cc3321704ecd17c93cf68c99c35467a8a97ffaaed53207e9b2da6ae0308ee1"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:9be84ff6d47fd61462be7523b49d7ba01adf67ce4e1447eae37721ab32464dd8"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:d82f681c9a9d933a9d8068e8e382977768e7779ddb8870fa0cf918d8250d1532"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:04c607029ae3660fb1624ed273811ffe09d57d84287d37e63b5b802a35897329"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72b61332f1b439c14cbd3815174a8f1d35067a02047c32decd406b3a09bb9890"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8214820990d01b52845f9fbcb92d2b7384a0c321b303e3ac614c219dc7d1d3af"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:462e0ab8dd7c7b70bfd6e3195eebc177549ede5cf3189814850c76f9a340d7ce"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-win32.whl", hash = "sha256:fa107460c842e4c1a6266150881694fefd4f33baa544ea9489601810c2210ef8"}, + {file = "grpcio_tools-1.62.2-cp312-cp312-win_amd64.whl", hash = "sha256:759c60f24c33a181bbbc1232a6752f9b49fbb1583312a4917e2b389fea0fb0f2"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-linux_armv7l.whl", hash = "sha256:45db5da2bcfa88f2b86b57ef35daaae85c60bd6754a051d35d9449c959925b57"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:ab84bae88597133f6ea7a2bdc57b2fda98a266fe8d8d4763652cbefd20e73ad7"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:7a49bccae1c7d154b78e991885c3111c9ad8c8fa98e91233de425718f47c6139"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7e439476b29d6dac363b321781a113794397afceeb97dad85349db5f1cb5e9a"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ea369c4d1567d1acdf69c8ea74144f4ccad9e545df7f9a4fc64c94fa7684ba3"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4f955702dc4b530696375251319d05223b729ed24e8673c2129f7a75d2caefbb"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3708a747aa4b6b505727282ca887041174e146ae030ebcadaf4c1d346858df62"}, + {file = "grpcio_tools-1.62.2-cp37-cp37m-win_amd64.whl", hash = "sha256:2ce149ea55eadb486a7fb75a20f63ef3ac065ee6a0240ed25f3549ce7954c653"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-linux_armv7l.whl", hash = "sha256:58cbb24b3fa6ae35aa9c210fcea3a51aa5fef0cd25618eb4fd94f746d5a9b703"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:6413581e14a80e0b4532577766cf0586de4dd33766a31b3eb5374a746771c07d"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:47117c8a7e861382470d0e22d336e5a91fdc5f851d1db44fa784b9acea190d87"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9f1ba79a253df9e553d20319c615fa2b429684580fa042dba618d7f6649ac7e4"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04a394cf5e51ba9be412eb9f6c482b6270bd81016e033e8eb7d21b8cc28fe8b5"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3c53b221378b035ae2f1881cbc3aca42a6075a8e90e1a342c2f205eb1d1aa6a1"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:c384c838b34d1b67068e51b5bbe49caa6aa3633acd158f1ab16b5da8d226bc53"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-win32.whl", hash = "sha256:19ea69e41c3565932aa28a202d1875ec56786aea46a2eab54a3b28e8a27f9517"}, + {file = "grpcio_tools-1.62.2-cp38-cp38-win_amd64.whl", hash = "sha256:1d768a5c07279a4c461ebf52d0cec1c6ca85c6291c71ec2703fe3c3e7e28e8c4"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-linux_armv7l.whl", hash = "sha256:5b07b5874187e170edfbd7aa2ca3a54ebf3b2952487653e8c0b0d83601c33035"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:d58389fe8be206ddfb4fa703db1e24c956856fcb9a81da62b13577b3a8f7fda7"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:7d8b4e00c3d7237b92260fc18a561cd81f1da82e8be100db1b7d816250defc66"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fe08d2038f2b7c53259b5c49e0ad08c8e0ce2b548d8185993e7ef67e8592cca"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19216e1fb26dbe23d12a810517e1b3fbb8d4f98b1a3fbebeec9d93a79f092de4"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b8574469ecc4ff41d6bb95f44e0297cdb0d95bade388552a9a444db9cd7485cd"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4f6f32d39283ea834a493fccf0ebe9cfddee7577bdcc27736ad4be1732a36399"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-win32.whl", hash = "sha256:76eb459bdf3fb666e01883270beee18f3f11ed44488486b61cd210b4e0e17cc1"}, + {file = "grpcio_tools-1.62.2-cp39-cp39-win_amd64.whl", hash = "sha256:217c2ee6a7ce519a55958b8622e21804f6fdb774db08c322f4c9536c35fdce7c"}, +] + +[package.dependencies] +grpcio = ">=1.62.2" +protobuf = ">=4.21.6,<5.0dev" +setuptools = "*" + [[package]] name = "h11" version = "0.14.0" @@ -1800,6 +1923,32 @@ files = [ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, ] +[[package]] +name = "h2" +version = "4.1.0" +description = "HTTP/2 State-Machine based protocol implementation" +optional = true +python-versions = ">=3.6.1" +files = [ + {file = "h2-4.1.0-py3-none-any.whl", hash = "sha256:03a46bcf682256c95b5fd9e9a99c1323584c3eec6440d379b9903d709476bc6d"}, + {file = "h2-4.1.0.tar.gz", hash = "sha256:a83aca08fbe7aacb79fec788c9c0bac936343560ed9ec18b82a13a12c28d2abb"}, +] + +[package.dependencies] +hpack = ">=4.0,<5" +hyperframe = ">=6.0,<7" + +[[package]] +name = "hpack" +version = "4.0.0" +description = "Pure-Python HPACK header compression" +optional = true +python-versions = ">=3.6.1" +files = [ + {file = "hpack-4.0.0-py3-none-any.whl", hash = "sha256:84a076fad3dc9a9f8063ccb8041ef100867b1878b25ef0ee63847a5d53818a6c"}, + {file = "hpack-4.0.0.tar.gz", hash = "sha256:fc41de0c63e687ebffde81187a948221294896f6bdc0ae2312708df339430095"}, +] + [[package]] name = "htmldate" version = "1.8.1" @@ -1843,6 +1992,20 @@ http2 = ["h2 (>=3,<5)"] socks = ["socksio (==1.*)"] trio = ["trio (>=0.22.0,<0.26.0)"] +[[package]] +name = "httplib2" +version = "0.22.0" +description = "A comprehensive HTTP client library." +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "httplib2-0.22.0-py3-none-any.whl", hash = "sha256:14ae0a53c1ba8f3d37e9e27cf37eabb0fb9980f435ba405d546948b009dd64dc"}, + {file = "httplib2-0.22.0.tar.gz", hash = "sha256:d7a10bc5ef5ab08322488bde8c726eeee5c8618723fdb399597ec58f3d82df81"}, +] + +[package.dependencies] +pyparsing = {version = ">=2.4.2,<3.0.0 || >3.0.0,<3.0.1 || >3.0.1,<3.0.2 || >3.0.2,<3.0.3 || >3.0.3,<4", markers = "python_version > \"3.0\""} + [[package]] name = "httpx" version = "0.27.0" @@ -1857,6 +2020,7 @@ files = [ [package.dependencies] anyio = "*" certifi = "*" +h2 = {version = ">=3,<5", optional = true, markers = "extra == \"http2\""} httpcore = "==1.*" idna = "*" sniffio = "*" @@ -1912,6 +2076,17 @@ testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gr torch = ["safetensors", "torch"] typing = ["types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)"] +[[package]] +name = "hyperframe" +version = "6.0.1" +description = "HTTP/2 framing layer for Python" +optional = true +python-versions = ">=3.6.1" +files = [ + {file = "hyperframe-6.0.1-py3-none-any.whl", hash = "sha256:0ec6bafd80d8ad2195c4f03aacba3a8265e57bc4cff261e802bf39970ed02a15"}, + {file = "hyperframe-6.0.1.tar.gz", hash = "sha256:ae510046231dc8e9ecb1a6586f63d2347bf4c8905914aa84ba585ae85f28a914"}, +] + [[package]] name = "identify" version = "2.5.36" @@ -3291,6 +3466,7 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ + {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4abe7fef64914ccfa909bc2ba39739670ecc9e820c83ccc7a6ed414122599b83"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1"}, ] @@ -3367,6 +3543,61 @@ develop = ["black", "botocore", "coverage (<8.0.0)", "jinja2", "mock", "myst-par docs = ["aiohttp (>=3,<4)", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] kerberos = ["requests-kerberos"] +[[package]] +name = "orjson" +version = "3.10.5" +description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" +optional = true +python-versions = ">=3.8" +files = [ + {file = "orjson-3.10.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63"}, + {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c"}, + {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96"}, + {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b"}, + {file = "orjson-3.10.5-cp310-none-win32.whl", hash = "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2"}, + {file = "orjson-3.10.5-cp310-none-win_amd64.whl", hash = "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228"}, + {file = "orjson-3.10.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1"}, + {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5"}, + {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f"}, + {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa"}, + {file = "orjson-3.10.5-cp311-none-win32.whl", hash = "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04"}, + {file = "orjson-3.10.5-cp311-none-win_amd64.whl", hash = "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c"}, + {file = "orjson-3.10.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969"}, + {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b"}, + {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211"}, + {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3"}, + {file = "orjson-3.10.5-cp312-none-win32.whl", hash = "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2"}, + {file = "orjson-3.10.5-cp312-none-win_amd64.whl", hash = "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5"}, + {file = "orjson-3.10.5-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d"}, + {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e"}, + {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9"}, + {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b"}, + {file = "orjson-3.10.5-cp38-none-win32.whl", hash = "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4"}, + {file = "orjson-3.10.5-cp38-none-win_amd64.whl", hash = "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09"}, + {file = "orjson-3.10.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139"}, + {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214"}, + {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595"}, + {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86"}, + {file = "orjson-3.10.5-cp39-none-win32.whl", hash = "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47"}, + {file = "orjson-3.10.5-cp39-none-win_amd64.whl", hash = "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7"}, + {file = "orjson-3.10.5.tar.gz", hash = "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d"}, +] + [[package]] name = "packaging" version = "24.0" @@ -3663,6 +3894,25 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "portalocker" +version = "2.8.2" +description = "Wraps the portalocker recipe for easy usage" +optional = true +python-versions = ">=3.8" +files = [ + {file = "portalocker-2.8.2-py3-none-any.whl", hash = "sha256:cfb86acc09b9aa7c3b43594e19be1345b9d16af3feb08bf92f23d4dce513a28e"}, + {file = "portalocker-2.8.2.tar.gz", hash = "sha256:2b035aa7828e46c58e9b31390ee1f169b98e1066ab10b9a6a861fe7e25ee4f33"}, +] + +[package.dependencies] +pywin32 = {version = ">=226", markers = "platform_system == \"Windows\""} + +[package.extras] +docs = ["sphinx (>=1.7.1)"] +redis = ["redis"] +tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)", "types-redis"] + [[package]] name = "pprintpp" version = "0.4.0" @@ -3925,47 +4175,47 @@ files = [ [[package]] name = "pydantic" -version = "1.10.15" +version = "1.10.16" description = "Data validation and settings management using python type hints" optional = false python-versions = ">=3.7" files = [ - {file = "pydantic-1.10.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22ed12ee588b1df028a2aa5d66f07bf8f8b4c8579c2e96d5a9c1f96b77f3bb55"}, - {file = "pydantic-1.10.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:75279d3cac98186b6ebc2597b06bcbc7244744f6b0b44a23e4ef01e5683cc0d2"}, - {file = "pydantic-1.10.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50f1666a9940d3d68683c9d96e39640f709d7a72ff8702987dab1761036206bb"}, - {file = "pydantic-1.10.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82790d4753ee5d00739d6cb5cf56bceb186d9d6ce134aca3ba7befb1eedbc2c8"}, - {file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d207d5b87f6cbefbdb1198154292faee8017d7495a54ae58db06762004500d00"}, - {file = "pydantic-1.10.15-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e49db944fad339b2ccb80128ffd3f8af076f9f287197a480bf1e4ca053a866f0"}, - {file = "pydantic-1.10.15-cp310-cp310-win_amd64.whl", hash = "sha256:d3b5c4cbd0c9cb61bbbb19ce335e1f8ab87a811f6d589ed52b0254cf585d709c"}, - {file = "pydantic-1.10.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c3d5731a120752248844676bf92f25a12f6e45425e63ce22e0849297a093b5b0"}, - {file = "pydantic-1.10.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c365ad9c394f9eeffcb30a82f4246c0006417f03a7c0f8315d6211f25f7cb654"}, - {file = "pydantic-1.10.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3287e1614393119c67bd4404f46e33ae3be3ed4cd10360b48d0a4459f420c6a3"}, - {file = "pydantic-1.10.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be51dd2c8596b25fe43c0a4a59c2bee4f18d88efb8031188f9e7ddc6b469cf44"}, - {file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6a51a1dd4aa7b3f1317f65493a182d3cff708385327c1c82c81e4a9d6d65b2e4"}, - {file = "pydantic-1.10.15-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4e316e54b5775d1eb59187f9290aeb38acf620e10f7fd2f776d97bb788199e53"}, - {file = "pydantic-1.10.15-cp311-cp311-win_amd64.whl", hash = "sha256:0d142fa1b8f2f0ae11ddd5e3e317dcac060b951d605fda26ca9b234b92214986"}, - {file = "pydantic-1.10.15-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7ea210336b891f5ea334f8fc9f8f862b87acd5d4a0cbc9e3e208e7aa1775dabf"}, - {file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3453685ccd7140715e05f2193d64030101eaad26076fad4e246c1cc97e1bb30d"}, - {file = "pydantic-1.10.15-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bea1f03b8d4e8e86702c918ccfd5d947ac268f0f0cc6ed71782e4b09353b26f"}, - {file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:005655cabc29081de8243126e036f2065bd7ea5b9dff95fde6d2c642d39755de"}, - {file = "pydantic-1.10.15-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:af9850d98fc21e5bc24ea9e35dd80a29faf6462c608728a110c0a30b595e58b7"}, - {file = "pydantic-1.10.15-cp37-cp37m-win_amd64.whl", hash = "sha256:d31ee5b14a82c9afe2bd26aaa405293d4237d0591527d9129ce36e58f19f95c1"}, - {file = "pydantic-1.10.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5e09c19df304b8123938dc3c53d3d3be6ec74b9d7d0d80f4f4b5432ae16c2022"}, - {file = "pydantic-1.10.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7ac9237cd62947db00a0d16acf2f3e00d1ae9d3bd602b9c415f93e7a9fc10528"}, - {file = "pydantic-1.10.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:584f2d4c98ffec420e02305cf675857bae03c9d617fcfdc34946b1160213a948"}, - {file = "pydantic-1.10.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bbc6989fad0c030bd70a0b6f626f98a862224bc2b1e36bfc531ea2facc0a340c"}, - {file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d573082c6ef99336f2cb5b667b781d2f776d4af311574fb53d908517ba523c22"}, - {file = "pydantic-1.10.15-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6bd7030c9abc80134087d8b6e7aa957e43d35714daa116aced57269a445b8f7b"}, - {file = "pydantic-1.10.15-cp38-cp38-win_amd64.whl", hash = "sha256:3350f527bb04138f8aff932dc828f154847fbdc7a1a44c240fbfff1b57f49a12"}, - {file = "pydantic-1.10.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:51d405b42f1b86703555797270e4970a9f9bd7953f3990142e69d1037f9d9e51"}, - {file = "pydantic-1.10.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a980a77c52723b0dc56640ced396b73a024d4b74f02bcb2d21dbbac1debbe9d0"}, - {file = "pydantic-1.10.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67f1a1fb467d3f49e1708a3f632b11c69fccb4e748a325d5a491ddc7b5d22383"}, - {file = "pydantic-1.10.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:676ed48f2c5bbad835f1a8ed8a6d44c1cd5a21121116d2ac40bd1cd3619746ed"}, - {file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:92229f73400b80c13afcd050687f4d7e88de9234d74b27e6728aa689abcf58cc"}, - {file = "pydantic-1.10.15-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2746189100c646682eff0bce95efa7d2e203420d8e1c613dc0c6b4c1d9c1fde4"}, - {file = "pydantic-1.10.15-cp39-cp39-win_amd64.whl", hash = "sha256:394f08750bd8eaad714718812e7fab615f873b3cdd0b9d84e76e51ef3b50b6b7"}, - {file = "pydantic-1.10.15-py3-none-any.whl", hash = "sha256:28e552a060ba2740d0d2aabe35162652c1459a0b9069fe0db7f4ee0e18e74d58"}, - {file = "pydantic-1.10.15.tar.gz", hash = "sha256:ca832e124eda231a60a041da4f013e3ff24949d94a01154b137fc2f2a43c3ffb"}, + {file = "pydantic-1.10.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1a539ac40551b01a85e899829aa43ca8036707474af8d74b48be288d4d2d2846"}, + {file = "pydantic-1.10.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a4fcc7b0b8038dbda2dda642cff024032dfae24a7960cc58e57a39eb1949b9b"}, + {file = "pydantic-1.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4660dd697de1ae2d4305a85161312611f64d5360663a9ba026cd6ad9e3fe14c3"}, + {file = "pydantic-1.10.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:900a787c574f903a97d0bf52a43ff3b6cf4fa0119674bcfc0e5fd1056d388ad9"}, + {file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d30192a63e6d3334c3f0c0506dd6ae9f1dce7b2f8845518915291393a5707a22"}, + {file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:16cf23ed599ca5ca937e37ba50ab114e6b5c387eb43a6cc533701605ad1be611"}, + {file = "pydantic-1.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:8d23111f41d1e19334edd51438fd57933f3eee7d9d2fa8cc3f5eda515a272055"}, + {file = "pydantic-1.10.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef287b8d7fc0e86a8bd1f902c61aff6ba9479c50563242fe88ba39692e98e1e0"}, + {file = "pydantic-1.10.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b9ded699bfd3b3912d796ff388b0c607e6d35d41053d37aaf8fd6082c660de9a"}, + {file = "pydantic-1.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:daeb199814333e4426c5e86d7fb610f4e230289f28cab90eb4de27330bef93cf"}, + {file = "pydantic-1.10.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5973843f1fa99ec6c3ac8d1a8698ac9340b35e45cca6c3e5beb5c3bd1ef15de6"}, + {file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6b8a7788a8528a558828fe4a48783cafdcf2612d13c491594a8161dc721629c"}, + {file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8abaecf54dacc9d991dda93c3b880d41092a8924cde94eeb811d7d9ab55df7d8"}, + {file = "pydantic-1.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:ddc7b682fbd23f051edc419dc6977e11dd2dbdd0cef9d05f0e15d1387862d230"}, + {file = "pydantic-1.10.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:067c2b5539f7839653ad8c3d1fc2f1343338da8677b7b2172abf3cd3fdc8f719"}, + {file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d1fc943583c046ecad0ff5d6281ee571b64e11b5503d9595febdce54f38b290"}, + {file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18548b30ccebe71d380b0886cc44ea5d80afbcc155e3518792f13677ad06097d"}, + {file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4e92292f9580fc5ea517618580fac24e9f6dc5657196e977c194a8e50e14f5a9"}, + {file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5da8bc4bb4f85b8c97cc7f11141fddbbd29eb25e843672e5807e19cc3d7c1b7f"}, + {file = "pydantic-1.10.16-cp37-cp37m-win_amd64.whl", hash = "sha256:a04ee1ea34172b87707a6ecfcdb120d7656892206b7c4dbdb771a73e90179fcb"}, + {file = "pydantic-1.10.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4fa86469fd46e732242c7acb83282d33f83591a7e06f840481327d5bf6d96112"}, + {file = "pydantic-1.10.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:89c2783dc261726fe7a5ce1121bce29a2f7eb9b1e704c68df2b117604e3b346f"}, + {file = "pydantic-1.10.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78e59fa919fa7a192f423d190d8660c35dd444efa9216662273f36826765424b"}, + {file = "pydantic-1.10.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7e82a80068c77f4b074032e031e642530b6d45cb8121fc7c99faa31fb6c6b72"}, + {file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d82d5956cee27a30e26a5b88d00a6a2a15a4855e13c9baf50175976de0dc282c"}, + {file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b7b99424cc0970ff08deccb549b5a6ec1040c0b449eab91723e64df2bd8fdca"}, + {file = "pydantic-1.10.16-cp38-cp38-win_amd64.whl", hash = "sha256:d97a35e1ba59442775201657171f601a2879e63517a55862a51f8d67cdfc0017"}, + {file = "pydantic-1.10.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9d91f6866fd3e303c632207813ef6bc4d86055e21c5e5a0a311983a9ac5f0192"}, + {file = "pydantic-1.10.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8d3c71d14c8bd26d2350c081908dbf59d5a6a8f9596d9ef2b09cc1e61c8662b"}, + {file = "pydantic-1.10.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b73e6386b439b4881d79244e9fc1e32d1e31e8d784673f5d58a000550c94a6c0"}, + {file = "pydantic-1.10.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f039881fb2ef86f6de6eacce6e71701b47500355738367413ccc1550b2a69cf"}, + {file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3895ddb26f22bdddee7e49741486aa7b389258c6f6771943e87fc00eabd79134"}, + {file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55b945da2756b5cef93d792521ad0d457fdf2f69fd5a2d10a27513f5281717dd"}, + {file = "pydantic-1.10.16-cp39-cp39-win_amd64.whl", hash = "sha256:22dd265c77c3976a34be78409b128cb84629284dfd1b69d2fa1507a36f84dc8b"}, + {file = "pydantic-1.10.16-py3-none-any.whl", hash = "sha256:aa2774ba5412fd1c5cb890d08e8b0a3bb5765898913ba1f61a65a4810f03cf29"}, + {file = "pydantic-1.10.16.tar.gz", hash = "sha256:8bb388f6244809af69ee384900b10b677a69f1980fdc655ea419710cffcb5610"}, ] [package.dependencies] @@ -4166,6 +4416,20 @@ cryptography = ">=41.0.5,<43" docs = ["sphinx (!=5.2.0,!=5.2.0.post0,!=7.2.5)", "sphinx-rtd-theme"] test = ["pretend", "pytest (>=3.0.1)", "pytest-rerunfailures"] +[[package]] +name = "pyparsing" +version = "3.1.2" +description = "pyparsing module - Classes and methods to define and execute parsing grammars" +optional = true +python-versions = ">=3.6.8" +files = [ + {file = "pyparsing-3.1.2-py3-none-any.whl", hash = "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742"}, + {file = "pyparsing-3.1.2.tar.gz", hash = "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad"}, +] + +[package.extras] +diagrams = ["jinja2", "railroad-diagrams"] + [[package]] name = "pypdf" version = "3.17.4" @@ -4187,15 +4451,75 @@ docs = ["myst_parser", "sphinx", "sphinx_rtd_theme"] full = ["Pillow (>=8.0.0)", "PyCryptodome", "cryptography"] image = ["Pillow (>=8.0.0)"] +[[package]] +name = "pyreqwest-impersonate" +version = "0.4.8" +description = "HTTP client that can impersonate web browsers, mimicking their headers and `TLS/JA3/JA4/HTTP2` fingerprints" +optional = true +python-versions = ">=3.8" +files = [ + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:45cad57afe4e6f56078ed9a7a90d0dc839d19d3e7a70175c80af21017f383bfb"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1986600253baf38f25fd07b8bdc1903359c26e5d34beb7d7d084845554b5664d"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cca4e6e59b9ad0cd20bad6caed3ac96992cd9c1d3126ecdfcab2c0ac2b75376"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab6b32544491ee655264dab86fc8a58e47c4f87d196b28022d4007faf971a50"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:64bd6299e7fc888bb7f7292cf3e29504c406e5d5d04afd37ca994ab8142d8ee4"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e914b650dd953b8d9b24ef56aa4ecbfc16e399227b68accd818f8bf159e0c558"}, + {file = "pyreqwest_impersonate-0.4.8-cp310-none-win_amd64.whl", hash = "sha256:cb56a2149b0c4548a8e0158b071a943f33dae9b717f92b5c9ac34ccd1f5a958c"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f62620e023490902feca0109f306e122e427feff7d59e03ecd22c69a89452367"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:08d4c01d76da88cfe3d7d03b311b375ce3fb5a59130f93f0637bb755d6e56ff1"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524e276bc460176c79d7ba4b9131d9db73c534586660371ebdf067749252a33"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22863bc0aaf02ca2f5d76c8130929ae680b7d82dfc1c28c1ed5f306ff626928"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8cc82d57f6a91037e64a7aa9122f909576ef2a141a42ce599958ef9f8c4bc033"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da8a053308210e44fd8349f07f45442a0691ac932f2881e98b05cf9ac404b091"}, + {file = "pyreqwest_impersonate-0.4.8-cp311-none-win_amd64.whl", hash = "sha256:4baf3916c14364a815a64ead7f728afb61b37541933b2771f18dbb245029bb55"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:78db05deed0b32c9c75f2b3168a3a9b7d5e36487b218cb839bfe7e2a143450cb"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9af9446d605903c2b4e94621a9093f8d8a403729bc9cbfbcb62929f8238c838f"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c55890181d8d81e66cac25a95e215dc9680645d01e9091b64449d5407ad9bc6"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69344e7ae9964502a8693da7ad77ebc3e1418ee197e2e394bc23c5d4970772a"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b5db5c957a10d8cc2815085ba0b8fe09245b2f94c2225d9653a854a03b4217e1"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03c19c21f63f9c91c590c4bbcc32cc2d8066b508c683a1d163b8c7d9816a01d5"}, + {file = "pyreqwest_impersonate-0.4.8-cp312-none-win_amd64.whl", hash = "sha256:0230610779129f74ff802c744643ce7589b1d07cba21d046fe3b574281c29581"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b8cb9471ab4b2fa7e80d3ac4e580249ff988d782f2938ad1f0428433652b170d"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8081a5ace2658be91519902bde9ddc5f94e1f850a39be196007a25e3da5bbfdc"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69eababfa3200459276acd780a0f3eaf41d1fe7c02bd169e714cba422055b5b9"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632957fa671ebb841166e40913015de457225cb73600ef250c436c280e68bf45"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2ce7ddef334b4e5c68f5ea1da1d65f686b8d84f4443059d128e0f069d3fa499a"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6ce333d450b158d582e36317089a006440b4e66739a8e8849d170e4cb15e8c8d"}, + {file = "pyreqwest_impersonate-0.4.8-cp38-none-win_amd64.whl", hash = "sha256:9d9c85ce19db92362854f534807e470f03e905f283a7de6826dc79b790a8788e"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2503277f2a95a30e28e498570e2ed03ef4302f873054e8e21d6c0e607cbbc1d1"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8260395ef4ddae325e8b30cef0391adde7bd35e1a1decf8c729e26391f09b52d"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d8066b46d82bbaff5402d767e2f13d3449b8191c37bf8283e91d301a7159869"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9c42f6343cfbd6663fb53edc9eb9feb4ebf6186b284e22368adc1eeb6a33854"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff534f491a059e74fb7f994876df86078b4b125dbecc53c098a298ecd55fa9c6"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b8fbf73b3ac513ddadafd338d61f79cd2370f0691d9175b2b92a45920920d6b"}, + {file = "pyreqwest_impersonate-0.4.8-cp39-none-win_amd64.whl", hash = "sha256:a26447c82665d0e361207c1a15e56b0ca54974aa6c1fdfa18c68f908dec78cbe"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24a16b8d55309f0af0db9d04ff442b0c91afccf078a94809e7c3a71747a5c214"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c8fada56465fc19179404cc9d5d5e1064f5dfe27405cb052f57a5b4fe06aed1"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a3d48d5abc146fd804395713427d944757a99254350e6a651e7d776818074aee"}, + {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:475829fe9994c66258157a8d4adb1c038f44f79f901208ba656d547842337227"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef1ec0e97623bc0e18469418cc4dd2c59a2d5fddcae944de61e13c0b46f910e"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91857b196de89e9b36d3f8629aa8772c0bbe7efef8334fe266956b1c192ec31c"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:63831e407487b8a21bb51f97cd86a616c291d5138f8caec16ab6019cf6423935"}, + {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c30e61de93bcd0a9d3ca226b1ae5475002afde61e9d85018a6a4a040eeb86567"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c72c37b03bce9900f5dbb4f476af17253ec60c13bf7a7259f71a8dc1b036cb"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f1096165741b5c2178ab15b0eb09b5de16dd39b1cc135767d72471f0a69ce"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:70c940c0e4ef335e22a6c705b01f286ee44780b5909065d212d94d82ea2580cb"}, + {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81c06f21757602d85f16dbc1cbaee1121cd65455f65aed4c048b7dcda7be85c4"}, + {file = "pyreqwest_impersonate-0.4.8.tar.gz", hash = "sha256:1eba11d47bd17244c64fec1502cc26ee66cc5c8a3be131e408101ae2b455e5bc"}, +] + +[package.extras] +dev = ["pytest (>=8.1.1)"] + [[package]] name = "pyright" -version = "1.1.363" +version = "1.1.370" description = "Command line wrapper for pyright" optional = false python-versions = ">=3.7" files = [ - {file = "pyright-1.1.363-py3-none-any.whl", hash = "sha256:d3b8d73c8d230e26cc3523862f3398032a0c39a00d7bb69dc0f595f8e888fd01"}, - {file = "pyright-1.1.363.tar.gz", hash = "sha256:00a8f0ae0e339473bb0488f8a2a2dcdf574e94a16cd7b4390d49d144714d8db2"}, + {file = "pyright-1.1.370-py3-none-any.whl", hash = "sha256:fc721601e480a69989775bfc210534a6ca0110ebd0c065244a8d3a151294fc61"}, + {file = "pyright-1.1.370.tar.gz", hash = "sha256:d0d559d506fc41e3297f721aaa05a1b9f06beda5acc9ac64ca371ce94c28f960"}, ] [package.dependencies] @@ -4386,7 +4710,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -4394,15 +4717,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -4419,7 +4735,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -4427,7 +4742,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -4447,6 +4761,32 @@ files = [ [package.dependencies] pyyaml = "*" +[[package]] +name = "qdrant-client" +version = "1.9.1" +description = "Client library for the Qdrant vector search engine" +optional = true +python-versions = ">=3.8" +files = [ + {file = "qdrant_client-1.9.1-py3-none-any.whl", hash = "sha256:b9b7e0e5c1a51410d8bb5106a869a51e12f92ab45a99030f27aba790553bd2c8"}, + {file = "qdrant_client-1.9.1.tar.gz", hash = "sha256:186b9c31d95aefe8f2db84b7746402d7365bd63b305550e530e31bde2002ce79"}, +] + +[package.dependencies] +grpcio = ">=1.41.0" +grpcio-tools = ">=1.41.0" +httpx = {version = ">=0.20.0", extras = ["http2"]} +numpy = [ + {version = ">=1.21", markers = "python_version >= \"3.8\" and python_version < \"3.12\""}, + {version = ">=1.26", markers = "python_version >= \"3.12\""}, +] +portalocker = ">=2.7.0,<3.0.0" +pydantic = ">=1.10.8" +urllib3 = ">=1.26.14,<3" + +[package.extras] +fastembed = ["fastembed (==0.2.6)"] + [[package]] name = "readme-renderer" version = "43.0" @@ -4574,13 +4914,13 @@ files = [ [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -5779,6 +6119,25 @@ files = [ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, ] +[[package]] +name = "typos" +version = "1.22.9" +description = "Source Code Spelling Correction" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typos-1.22.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6221400b82554f853e1d1a0f26bcfddf9f36008114d3441c566e1b5edf20d27d"}, + {file = "typos-1.22.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a57b5f0acd1596034fdc333f94d4713adbc181c545fb526cf2119d2af4c007ec"}, + {file = "typos-1.22.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77e2d9dfee24cccf177b09d8ace6d6012fa8c453aa092d869426bfef3dd8c67e"}, + {file = "typos-1.22.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c38886031f4570d546b63ec112aed6b323762022ca5cc64d52537724a1529257"}, + {file = "typos-1.22.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8577b482256538822f76c9825d36f76b7b1e7cbccf2842279a7b46f0494796a5"}, + {file = "typos-1.22.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:63f7ae86eb7dccc43845bf0ef72a3746b1022889a178809c028f809081c6f20d"}, + {file = "typos-1.22.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5f290b85f1dddc875d4efa0b22802413f86532b99fa0ac2cb8d2e70eda68acfd"}, + {file = "typos-1.22.9-py3-none-win32.whl", hash = "sha256:76a58b1d54ee00ef8d90c3166b149e70d84b0414617a34abf5ded1db76feecef"}, + {file = "typos-1.22.9-py3-none-win_amd64.whl", hash = "sha256:53f31a9c0d321132f680ab92d80f7c520e163c53c9042fb009feaa91d9b4a7c4"}, + {file = "typos-1.22.9.tar.gz", hash = "sha256:c7b5feada41ce26e34eea1145141887257e59384d0ceea00f0f03349335ff688"}, +] + [[package]] name = "tzdata" version = "2024.1" @@ -5807,15 +6166,26 @@ tzdata = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)", "zest.releaser"] +[[package]] +name = "uritemplate" +version = "4.1.1" +description = "Implementation of RFC 6570 URI Templates" +optional = true +python-versions = ">=3.6" +files = [ + {file = "uritemplate-4.1.1-py2.py3-none-any.whl", hash = "sha256:830c08b8d99bdd312ea4ead05994a38e8936266f84b9a7878232db50b044e02e"}, + {file = "uritemplate-4.1.1.tar.gz", hash = "sha256:4346edfc5c3b79f694bccd6d6099a322bbeb628dbf2cd86eea55a456ce5124f0"}, +] + [[package]] name = "urllib3" -version = "1.26.18" +version = "1.26.19" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, + {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, ] [package.extras] @@ -6141,7 +6511,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] @@ -6161,6 +6531,7 @@ drivers-prompt-google = ["google-generativeai"] drivers-prompt-huggingface = ["huggingface-hub", "transformers"] drivers-prompt-huggingface-pipeline = ["huggingface-hub", "torch", "transformers"] drivers-prompt-ollama = ["ollama"] +drivers-rerank-cohere = ["cohere"] drivers-sql-postgres = ["pgvector", "psycopg2-binary"] drivers-sql-redshift = ["boto3", "sqlalchemy-redshift"] drivers-sql-snowflake = ["snowflake-sqlalchemy"] @@ -6170,9 +6541,11 @@ drivers-vector-mongodb = ["pymongo"] drivers-vector-opensearch = ["opensearch-py"] drivers-vector-pinecone = ["pinecone-client"] drivers-vector-postgresql = ["pgvector", "psycopg2-binary"] +drivers-vector-qdrant = ["qdrant-client"] drivers-vector-redis = ["redis"] drivers-web-scraper-markdownify = ["beautifulsoup4", "markdownify", "playwright"] drivers-web-scraper-trafilatura = ["trafilatura"] +drivers-web-search-duckduckgo = ["duckduckgo-search"] loaders-audio = ["filetype"] loaders-dataframe = ["pandas"] loaders-email = ["mail-parser"] @@ -6182,4 +6555,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a20db0b979aa17d15d4669d91dde89ccbfc98bf93406013a1a0946298df2b39b" +content-hash = "a38d0f0671ff5deb42783721f4ce103e670a689f618e950451a807921f5d7139" diff --git a/pyproject.toml b/pyproject.toml index 77c4108da..c1b6b934c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ numpy = ">=1" stringcase = "^1.2.0" docker = "^7.1.0" sqlalchemy = "~=1.0" -requests = "^2" +requests = "^2.32.0" # drivers cohere = { version = "^5.5.4", optional = true } @@ -44,7 +44,7 @@ redis = { version = "^4.6.0", optional = true } opensearch-py = { version = "^2.3.1", optional = true } pgvector = { version = "^0.2.3", optional = true } psycopg2-binary = { version = "^2.9.9", optional = true } -google-generativeai = { version = "^0.4.1", optional = true } +google-generativeai = { version = "^0.7.0", optional = true } trafilatura = {version = "^1.6", optional = true} playwright = {version = "^1.42", optional = true} beautifulsoup4 = {version = "^4.12.3", optional = true} @@ -52,8 +52,10 @@ markdownify = {version = "^0.11.6", optional = true} voyageai = {version = "^0.2.1", optional = true} elevenlabs = {version = "^1.1.2", optional = true} torch = {version = "^2.3.0", optional = true} +qdrant-client = { version = ">=1.9.1", optional = true } pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} +duckduckgo-search = {version = "^6.1.6", optional = true} # loaders pandas = {version = "^1.3", optional = true} @@ -86,6 +88,7 @@ drivers-vector-redis = ["redis"] drivers-vector-opensearch = ["opensearch-py"] drivers-vector-amazon-opensearch = ["opensearch-py", "boto3"] drivers-vector-postgresql = ["pgvector", "psycopg2-binary"] +drivers-vector-qdrant = ["qdrant-client"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] @@ -97,10 +100,14 @@ drivers-embedding-cohere = ["cohere"] drivers-web-scraper-trafilatura = ["trafilatura"] drivers-web-scraper-markdownify = ["playwright", "beautifulsoup4", "markdownify"] +drivers-web-search-duckduckgo = ["duckduckgo-search"] + drivers-event-listener-amazon-sqs = ["boto3"] drivers-event-listener-amazon-iot = ["boto3"] drivers-event-listener-pusher = ["pusher"] +drivers-rerank-cohere = ["cohere"] + loaders-dataframe = ["pandas"] loaders-pdf = ["pypdf"] loaders-image = ["pillow"] @@ -119,6 +126,7 @@ all = [ "snowflake", "marqo", "pinecone-client", + "qdrant-client", "pymongo", "redis", "opensearch-py", @@ -134,6 +142,7 @@ all = [ "torch", "pusher", "ollama", + "duckduckgo-search", # loaders "pandas", @@ -168,6 +177,7 @@ ruff = "^0.4.6" pyright = "^1.1.363" pre-commit = "^3.7.1" boto3-stubs = {extras = ["bedrock", "iam", "opensearch", "s3", "sagemaker"], version = "^1.34.105"} +typos = "^1.22.9" [tool.poetry.group.docs] @@ -190,7 +200,22 @@ line-length = 120 skip-magic-trailing-comma = true [tool.ruff.lint] -select = ["E4", "E7", "E9", "F", "TID251"] +select = [ + "E", # pycodestyle + "F", # Pyflakes + "UP", # pyupgrade + "B", # flake8-bugbear + "SIM", # flake8-simplify + "TID251", # banned-api + "T201", # print +] +ignore = [ + "UP007", # non-pep604-annotation + "E501", # line-too-long + "B024", # abstract-base-class-without-abstract-method + "B009", # get-attr-with-constant + "B010", # set-attr-with-constant +] [tool.ruff.lint.flake8-tidy-imports.banned-api] "attr".msg = "The attr module is deprecated, use attrs instead." @@ -205,6 +230,7 @@ exclude = [ pythonVersion = "3.9" reportOptionalMemberAccess = "none" reportIncompatibleVariableOverride = "none" # see thread: https://github.com/microsoft/pyright/issues/5933 +enableExperimentalFeatures = true # https://github.com/microsoft/pyright/issues/7713 [tool.pytest_env] OPENAI_API_KEY = {value = "api-key", skip_if_set = true} diff --git a/tests/integration/tasks/test_text_query_task.py b/tests/integration/tasks/test_rag_task.py similarity index 65% rename from tests/integration/tasks/test_text_query_task.py rename to tests/integration/tasks/test_rag_task.py index beb478b33..c0383002c 100644 --- a/tests/integration/tasks/test_text_query_task.py +++ b/tests/integration/tasks/test_rag_task.py @@ -1,8 +1,10 @@ +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.utils.defaults import rag_engine from tests.utils.structure_tester import StructureTester import pytest -class TestTextQueryTask: +class TestRagTask: @pytest.fixture( autouse=True, params=StructureTester.TEXT_SUMMARY_TASK_CAPABLE_PROMPT_DRIVERS, @@ -10,22 +12,18 @@ class TestTextQueryTask: ) def structure_tester(self, request): from griptape.structures import Agent - from griptape.tasks import TextQueryTask + from griptape.tasks import RagTask from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver - from griptape.engines import VectorQueryEngine from griptape.artifacts import TextArtifact vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) - artifact = TextArtifact("John Doe works as as software engineer at Griptape.") + rag_engine_instance = rag_engine(MockPromptDriver(), vector_store_driver) - vector_query_engine = VectorQueryEngine(prompt_driver=request.param, vector_store_driver=vector_store_driver) - vector_query_engine.upsert_text_artifact(artifact=artifact) + vector_store_driver.upsert_text_artifact(artifact=artifact) agent = Agent(prompt_driver=request.param) - agent.add_task( - TextQueryTask("Respond to the users following query: {{ args[0] }}", query_engine=vector_query_engine) - ) + agent.add_task(RagTask("Respond to the users following query: {{ args[0] }}", rag_engine=rag_engine_instance)) return StructureTester(agent) diff --git a/tests/integration/tasks/test_toolkit_task.py b/tests/integration/tasks/test_toolkit_task.py index 97f068c5b..a4d8c30c3 100644 --- a/tests/integration/tasks/test_toolkit_task.py +++ b/tests/integration/tasks/test_toolkit_task.py @@ -12,13 +12,15 @@ def structure_tester(self, request): import os from griptape.structures import Agent from griptape.tools import WebScraper, WebSearch, TaskMemoryClient + from griptape.drivers import GoogleWebSearchDriver return StructureTester( Agent( tools=[ WebSearch( - google_api_key=os.environ["GOOGLE_API_KEY"], - google_api_search_id=os.environ["GOOGLE_API_SEARCH_ID"], + web_search_driver=GoogleWebSearchDriver( + api_key=os.environ["GOOGLE_API_KEY"], search_id=os.environ["GOOGLE_API_SEARCH_ID"] + ) ), WebScraper(off_prompt=True), TaskMemoryClient(off_prompt=False), diff --git a/tests/mocks/mock_failing_prompt_driver.py b/tests/mocks/mock_failing_prompt_driver.py index c97b25d86..0dbeb8fda 100644 --- a/tests/mocks/mock_failing_prompt_driver.py +++ b/tests/mocks/mock_failing_prompt_driver.py @@ -1,10 +1,11 @@ +from __future__ import annotations from collections.abc import Iterator from attrs import define -from griptape.utils import PromptStack -from griptape.drivers import BasePromptDriver -from griptape.tokenizers import OpenAiTokenizer, BaseTokenizer from griptape.artifacts import TextArtifact +from griptape.common import PromptStack, Message, TextMessageContent, DeltaMessage, TextDeltaMessageContent +from griptape.drivers import BasePromptDriver +from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer @define @@ -14,18 +15,25 @@ class MockFailingPromptDriver(BasePromptDriver): model: str = "test-model" tokenizer: BaseTokenizer = OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: + def try_run(self, prompt_stack: PromptStack) -> Message: if self.current_attempt < self.max_failures: self.current_attempt += 1 - raise Exception(f"failed attempt") + raise Exception("failed attempt") else: - return TextArtifact("success") + return Message( + content=[TextMessageContent(TextArtifact("success"))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=100, output_tokens=100), + ) - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: if self.current_attempt < self.max_failures: self.current_attempt += 1 - raise Exception(f"failed attempt") + raise Exception("failed attempt") else: - yield TextArtifact("success") + yield DeltaMessage( + content=TextDeltaMessageContent("success"), + usage=DeltaMessage.Usage(input_tokens=100, output_tokens=100), + ) diff --git a/tests/mocks/mock_prompt_driver.py b/tests/mocks/mock_prompt_driver.py index 3235f7cd5..4786b78a6 100644 --- a/tests/mocks/mock_prompt_driver.py +++ b/tests/mocks/mock_prompt_driver.py @@ -1,11 +1,15 @@ from __future__ import annotations + from collections.abc import Iterator from typing import Callable + from attrs import define, field -from griptape.utils import PromptStack + +from griptape.artifacts import TextArtifact +from griptape.common import PromptStack, Message, DeltaMessage, TextMessageContent, TextDeltaMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer -from griptape.artifacts import TextArtifact + from tests.mocks.mock_tokenizer import MockTokenizer @@ -16,12 +20,18 @@ class MockPromptDriver(BasePromptDriver): mock_input: str | Callable[[], str] = field(default="mock input", kw_only=True) mock_output: str | Callable[[PromptStack], str] = field(default="mock output", kw_only=True) - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - return TextArtifact( - value=self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output - ) + def try_run(self, prompt_stack: PromptStack) -> Message: + output = self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - yield TextArtifact( - value=self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output + return Message( + content=[TextMessageContent(TextArtifact(output))], + role=Message.ASSISTANT_ROLE, + usage=Message.Usage(input_tokens=100, output_tokens=100), ) + + def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: + output = self.mock_output(prompt_stack) if isinstance(self.mock_output, Callable) else self.mock_output + + yield DeltaMessage(content=TextDeltaMessageContent(output)) + + yield DeltaMessage(usage=DeltaMessage.Usage(input_tokens=100, output_tokens=100)) diff --git a/tests/mocks/mock_rag_module.py b/tests/mocks/mock_rag_module.py new file mode 100644 index 000000000..98b69cee8 --- /dev/null +++ b/tests/mocks/mock_rag_module.py @@ -0,0 +1,4 @@ +from griptape.engines.rag.modules import BaseRagModule + + +class MockRagModule(BaseRagModule): ... diff --git a/tests/mocks/mock_serializable.py b/tests/mocks/mock_serializable.py index 4de173b07..b02c071aa 100644 --- a/tests/mocks/mock_serializable.py +++ b/tests/mocks/mock_serializable.py @@ -5,7 +5,12 @@ @define class MockSerializable(SerializableMixin): + @define + class NestedMockSerializable(SerializableMixin): + foo: str = field(default="bar", kw_only=True, metadata={"serializable": True}) + foo: str = field(default="bar", kw_only=True, metadata={"serializable": True}) bar: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) baz: Optional[list[int]] = field(default=None, kw_only=True, metadata={"serializable": True}) secret: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) + nested: Optional[NestedMockSerializable] = field(default=None, kw_only=True, metadata={"serializable": True}) diff --git a/tests/mocks/mock_value_prompt_driver.py b/tests/mocks/mock_value_prompt_driver.py deleted file mode 100644 index 12ddeec9f..000000000 --- a/tests/mocks/mock_value_prompt_driver.py +++ /dev/null @@ -1,21 +0,0 @@ -from collections.abc import Iterator -from attrs import define, field, Factory -from griptape.drivers import BasePromptDriver -from griptape.tokenizers import OpenAiTokenizer, BaseTokenizer -from griptape.artifacts import TextArtifact -from griptape.utils.prompt_stack import PromptStack - - -@define -class MockValuePromptDriver(BasePromptDriver): - value: str = field(kw_only=True) - model: str = field(default="test-model") - tokenizer: BaseTokenizer = field( - default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)) - ) - - def try_run(self, prompt_stack: PromptStack) -> TextArtifact: - return TextArtifact(value=self.value) - - def try_stream(self, prompt_stack: PromptStack) -> Iterator[TextArtifact]: - yield TextArtifact(value=self.value) diff --git a/tests/unit/artifacts/test_boolean_artifact.py b/tests/unit/artifacts/test_boolean_artifact.py new file mode 100644 index 000000000..bcad67673 --- /dev/null +++ b/tests/unit/artifacts/test_boolean_artifact.py @@ -0,0 +1,35 @@ +import pytest +from griptape.artifacts import BooleanArtifact + + +class TestBooleanArtifact: + def test_parse_bool(self): + assert BooleanArtifact.parse_bool("true").value is True + assert BooleanArtifact.parse_bool("false").value is False + assert BooleanArtifact.parse_bool("True").value is True + assert BooleanArtifact.parse_bool("False").value is False + + with pytest.raises(ValueError): + BooleanArtifact.parse_bool("foo") + + with pytest.raises(ValueError): + BooleanArtifact.parse_bool(None) + + assert BooleanArtifact.parse_bool(True).value is True + assert BooleanArtifact.parse_bool(False).value is False + + def test_add(self): + with pytest.raises(ValueError): + BooleanArtifact(True) + BooleanArtifact(True) + + def test_value_type_conversion(self): + assert BooleanArtifact(1).value is True + assert BooleanArtifact(0).value is False + assert BooleanArtifact(True).value is True + assert BooleanArtifact(False).value is False + assert BooleanArtifact("true").value is True + assert BooleanArtifact("false").value is True + assert BooleanArtifact([1]).value is True + assert BooleanArtifact([]).value is False + assert BooleanArtifact(False) == False + assert BooleanArtifact(True) == True diff --git a/tests/unit/artifacts/test_text_artifact.py b/tests/unit/artifacts/test_text_artifact.py index f913429d7..6ea2c6697 100644 --- a/tests/unit/artifacts/test_text_artifact.py +++ b/tests/unit/artifacts/test_text_artifact.py @@ -61,3 +61,11 @@ def test_name(self): assert artifact.name == artifact.id assert TextArtifact("foo", name="bar").name == "bar" + + def test_meta(self): + artifact = TextArtifact("foo") + + assert artifact.meta == {} + + meta = {"foo": "bar"} + assert TextArtifact("foo", meta=meta).meta == meta diff --git a/tests/unit/config/test_amazon_bedrock_structure_config.py b/tests/unit/config/test_amazon_bedrock_structure_config.py index 44020b815..d75684829 100644 --- a/tests/unit/config/test_amazon_bedrock_structure_config.py +++ b/tests/unit/config/test_amazon_bedrock_structure_config.py @@ -1,3 +1,4 @@ +import boto3 from pytest import fixture from griptape.config import AmazonBedrockStructureConfig from tests.utils.aws import mock_aws_credentials @@ -10,8 +11,17 @@ def run_before_and_after_tests(self): @fixture def config(self): + mock_aws_credentials() return AmazonBedrockStructureConfig() + @fixture + def config_with_values(self): + return AmazonBedrockStructureConfig( + session=boto3.Session( + aws_access_key_id="testing", aws_secret_access_key="testing", region_name="region-value" + ) + ) + def test_to_dict(self, config): assert config.to_dict() == { "conversation_memory_driver": None, @@ -56,3 +66,52 @@ def test_to_dict(self, config): def test_from_dict(self, config): assert AmazonBedrockStructureConfig.from_dict(config.to_dict()).to_dict() == config.to_dict() + + def test_from_dict_with_values(self, config_with_values): + assert ( + AmazonBedrockStructureConfig.from_dict(config_with_values.to_dict()).to_dict() + == config_with_values.to_dict() + ) + + def test_to_dict_with_values(self, config_with_values): + assert config_with_values.to_dict() == { + "conversation_memory_driver": None, + "embedding_driver": {"model": "amazon.titan-embed-text-v1", "type": "AmazonBedrockTitanEmbeddingDriver"}, + "image_generation_driver": { + "image_generation_model_driver": { + "cfg_scale": 7, + "outpainting_mode": "PRECISE", + "quality": "standard", + "type": "BedrockTitanImageGenerationModelDriver", + }, + "image_height": 512, + "image_width": 512, + "model": "amazon.titan-image-generator-v1", + "seed": None, + "type": "AmazonBedrockImageGenerationDriver", + }, + "image_query_driver": { + "type": "AmazonBedrockImageQueryDriver", + "model": "anthropic.claude-3-5-sonnet-20240620-v1:0", + "max_tokens": 256, + "image_query_model_driver": {"type": "BedrockClaudeImageQueryModelDriver"}, + }, + "prompt_driver": { + "max_tokens": None, + "model": "anthropic.claude-3-5-sonnet-20240620-v1:0", + "stream": False, + "temperature": 0.1, + "type": "AmazonBedrockPromptDriver", + }, + "vector_store_driver": { + "embedding_driver": { + "model": "amazon.titan-embed-text-v1", + "type": "AmazonBedrockTitanEmbeddingDriver", + }, + "type": "LocalVectorStoreDriver", + }, + "type": "AmazonBedrockStructureConfig", + "text_to_speech_driver": {"type": "DummyTextToSpeechDriver"}, + "audio_transcription_driver": {"type": "DummyAudioTranscriptionDriver"}, + } + assert config_with_values.session.region_name == "region-value" diff --git a/tests/unit/config/test_google_structure_config.py b/tests/unit/config/test_google_structure_config.py index 72e623ff0..ad96f2a35 100644 --- a/tests/unit/config/test_google_structure_config.py +++ b/tests/unit/config/test_google_structure_config.py @@ -19,7 +19,7 @@ def test_to_dict(self, config): "temperature": 0.1, "max_tokens": None, "stream": False, - "model": "gemini-pro", + "model": "gemini-1.5-pro", "top_p": None, "top_k": None, }, diff --git a/tests/unit/drivers/event_listener/test_base_event_listener_driver.py b/tests/unit/drivers/event_listener/test_base_event_listener_driver.py index 6d33dd2a0..383c0be89 100644 --- a/tests/unit/drivers/event_listener/test_base_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_base_event_listener_driver.py @@ -1,8 +1,20 @@ +from unittest.mock import MagicMock from tests.mocks.mock_event import MockEvent from tests.mocks.mock_event_listener_driver import MockEventListenerDriver class TestBaseEventListenerDriver: + def test_publish_event(self): + executor = MagicMock() + executor.__enter__.return_value = executor + driver = MockEventListenerDriver(futures_executor_fn=lambda: executor) + + driver.publish_event(MockEvent().to_dict()) + + executor.__enter__.assert_called_once() + executor.submit.assert_called_once() + executor.__exit__.assert_called_once() + def test__safe_try_publish_event(self): driver = MockEventListenerDriver(batched=False) diff --git a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py index 285cf9510..8d1693ade 100644 --- a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py @@ -84,7 +84,7 @@ def test_validate_workdir(self, workdir, session, bucket): @pytest.mark.parametrize( "workdir,path,expected", [ - # Valid non-empty directories (witout trailing slash) + # Valid non-empty directories (without trailing slash) ("/", "", ["foo", "foo.txt", "foo-empty", "resources"]), ("/", "foo", ["bar", "bar.txt", "bar-empty"]), ("/", "foo/bar", ["baz.txt", "baz-empty"]), @@ -111,7 +111,7 @@ def test_validate_workdir(self, workdir, session, bucket): ("/./..", "bar/..", ["foo", "foo.txt", "foo-empty", "resources"]), ("/./..", "foo/.", ["bar", "bar.txt", "bar-empty"]), ("/./..", "foo/bar/.", ["baz.txt", "baz-empty"]), - # Empty folders (witout trailing slash) + # Empty folders (without trailing slash) ("/", "foo-empty", []), ("/", "foo/bar-empty", []), ("/", "foo/bar/baz-empty", []), diff --git a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py index 236281739..b3f4ec561 100644 --- a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py @@ -57,7 +57,7 @@ def test_validate_workdir(self): @pytest.mark.parametrize( "workdir,path,expected", [ - # Valid non-empty directories (witout trailing slash) + # Valid non-empty directories (without trailing slash) ("/", "", ["foo", "foo.txt", "foo-empty", "resources"]), ("/", "foo", ["bar", "bar.txt", "bar-empty"]), ("/", "foo/bar", ["baz.txt", "baz-empty"]), @@ -84,7 +84,7 @@ def test_validate_workdir(self): ("/./..", "bar/..", ["foo", "foo.txt", "foo-empty", "resources"]), ("/./..", "foo/.", ["bar", "bar.txt", "bar-empty"]), ("/./..", "foo/bar/.", ["baz.txt", "baz-empty"]), - # Empty folders (witout trailing slash) + # Empty folders (without trailing slash) ("/", "foo-empty", []), ("/", "foo/bar-empty", []), ("/", "foo/bar/baz-empty", []), diff --git a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py index ef3b0e1df..ba79a4def 100644 --- a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py @@ -60,6 +60,33 @@ def test_store(self): response = table.get_item(TableName=self.DYNAMODB_TABLE_NAME, Key={"entryId": "bar"}) assert "Item" in response + def test_store_with_sort_key(self): + session = boto3.Session(region_name=self.AWS_REGION) + dynamodb = session.resource("dynamodb") + table = dynamodb.Table(self.DYNAMODB_TABLE_NAME) + prompt_driver = MockPromptDriver() + memory_driver = AmazonDynamoDbConversationMemoryDriver( + session=session, + table_name=self.DYNAMODB_TABLE_NAME, + partition_key=self.DYNAMODB_PARTITION_KEY, + value_attribute_key=self.VALUE_ATTRIBUTE_KEY, + partition_key_value=self.PARTITION_KEY_VALUE, + sort_key="sortKey", + sort_key_value="foo", + ) + memory = ConversationMemory(driver=memory_driver) + pipeline = Pipeline(prompt_driver=prompt_driver, conversation_memory=memory) + + pipeline.add_task(PromptTask("test")) + + response = table.get_item(TableName=self.DYNAMODB_TABLE_NAME, Key={"entryId": "bar", "sortKey": "foo"}) + assert "Item" not in response + + pipeline.run() + + response = table.get_item(TableName=self.DYNAMODB_TABLE_NAME, Key={"entryId": "bar", "sortKey": "foo"}) + assert "Item" in response + def test_load(self): prompt_driver = MockPromptDriver() memory_driver = AmazonDynamoDbConversationMemoryDriver( @@ -81,5 +108,31 @@ def test_load(self): assert new_memory.type == "ConversationMemory" assert len(new_memory.runs) == 2 - assert new_memory.runs[0].input == "test" - assert new_memory.runs[0].output == "mock output" + assert new_memory.runs[0].input.value == "test" + assert new_memory.runs[0].output.value == "mock output" + + def test_load_with_sort_key(self): + prompt_driver = MockPromptDriver() + memory_driver = AmazonDynamoDbConversationMemoryDriver( + session=boto3.Session(region_name=self.AWS_REGION), + table_name=self.DYNAMODB_TABLE_NAME, + partition_key=self.DYNAMODB_PARTITION_KEY, + value_attribute_key=self.VALUE_ATTRIBUTE_KEY, + partition_key_value=self.PARTITION_KEY_VALUE, + sort_key="sortKey", + sort_key_value="foo", + ) + memory = ConversationMemory(driver=memory_driver) + pipeline = Pipeline(prompt_driver=prompt_driver, conversation_memory=memory) + + pipeline.add_task(PromptTask("test")) + + pipeline.run() + pipeline.run() + + new_memory = memory_driver.load() + + assert new_memory.type == "ConversationMemory" + assert len(new_memory.runs) == 2 + assert new_memory.runs[0].input.value == "test" + assert new_memory.runs[0].output.value == "mock output" diff --git a/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py index d12d5d3d2..c794afd0e 100644 --- a/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py @@ -52,8 +52,8 @@ def test_load(self): assert new_memory.type == "ConversationMemory" assert len(new_memory.runs) == 2 - assert new_memory.runs[0].input == "test" - assert new_memory.runs[0].output == "mock output" + assert new_memory.runs[0].input.value == "test" + assert new_memory.runs[0].output.value == "mock output" assert new_memory.max_runs == 5 def test_autoload(self): @@ -71,8 +71,8 @@ def test_autoload(self): assert autoloaded_memory.type == "ConversationMemory" assert len(autoloaded_memory.runs) == 2 - assert autoloaded_memory.runs[0].input == "test" - assert autoloaded_memory.runs[0].output == "mock output" + assert autoloaded_memory.runs[0].input.value == "test" + assert autoloaded_memory.runs[0].output.value == "mock output" def __delete_file(self, file_path): try: diff --git a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py index dee840508..1af9d74dc 100644 --- a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py @@ -3,9 +3,9 @@ from griptape.memory.structure.base_conversation_memory import BaseConversationMemory from griptape.drivers.memory.conversation.redis_conversation_memory_driver import RedisConversationMemoryDriver -TEST_CONVERSATION = '{"type": "ConversationMemory", "runs": [{"type": "Run", "id": "729ca6be5d79433d9762eb06dfd677e2", "input": "Hi There, Hello", "output": "Hello! How can I assist you today?"}], "max_runs": 2}' +TEST_CONVERSATION = '{"type": "ConversationMemory", "runs": [{"type": "Run", "id": "729ca6be5d79433d9762eb06dfd677e2", "input": {"type": "TextArtifact", "id": "1234", "value": "Hi There, Hello"}, "output": {"type": "TextArtifact", "id": "123", "value": "Hello! How can I assist you today?"}}], "max_runs": 2}' CONVERSATION_ID = "117151897f344ff684b553d0655d8f39" -INDEX = "griptape_converstaion" +INDEX = "griptape_conversation" HOST = "127.0.0.1" PORT = 6379 PASSWORD = "" diff --git a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py index 8aa345595..3cd165140 100644 --- a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py @@ -1,6 +1,7 @@ import pytest -from griptape.utils import PromptStack +from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.common import PromptStack from griptape.drivers import AmazonBedrockPromptDriver @@ -9,7 +10,10 @@ class TestAmazonBedrockPromptDriver: def mock_converse(self, mocker): mock_converse = mocker.patch("boto3.Session").return_value.client.return_value.converse - mock_converse.return_value = {"output": {"message": {"content": [{"text": "model-output"}]}}} + mock_converse.return_value = { + "output": {"message": {"content": [{"text": "model-output"}]}}, + "usage": {"inputTokens": 5, "outputTokens": 10}, + } return mock_converse @@ -17,26 +21,33 @@ def mock_converse(self, mocker): def mock_converse_stream(self, mocker): mock_converse_stream = mocker.patch("boto3.Session").return_value.client.return_value.converse_stream - mock_converse_stream.return_value = {"stream": [{"contentBlockDelta": {"delta": {"text": "model-output"}}}]} + mock_converse_stream.return_value = { + "stream": [ + {"contentBlockDelta": {"contentBlockIndex": 0, "delta": {"text": "model-output"}}}, + {"metadata": {"usage": {"inputTokens": 5, "outputTokens": 10}}}, + ] + } return mock_converse_stream - @pytest.fixture - def prompt_stack(self): + @pytest.fixture(params=[True, False]) + def prompt_stack(self, request): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + if request.param: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") return prompt_stack @pytest.fixture def messages(self): return [ - {"role": "user", "content": [{"text": "generic-input"}]}, - {"role": "system", "content": [{"text": "system-input"}]}, {"role": "user", "content": [{"text": "user-input"}]}, + {"role": "user", "content": [{"text": "user-input"}]}, + {"role": "user", "content": [{"image": {"format": "png", "source": {"bytes": b"image-data"}}}]}, {"role": "assistant", "content": [{"text": "assistant-input"}]}, ] @@ -50,34 +61,34 @@ def test_try_run(self, mock_converse, prompt_stack, messages): # Then mock_converse.assert_called_once_with( modelId=driver.model, - messages=[ - {"role": "user", "content": [{"text": "generic-input"}]}, - {"role": "user", "content": [{"text": "user-input"}]}, - {"role": "assistant", "content": [{"text": "assistant-input"}]}, - ], - system=[{"text": "system-input"}], + messages=messages, + **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), inferenceConfig={"temperature": driver.temperature}, additionalModelRequestFields={}, ) assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 def test_try_stream_run(self, mock_converse_stream, prompt_stack, messages): # Given driver = AmazonBedrockPromptDriver(model="ai21.j2", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_converse_stream.assert_called_once_with( modelId=driver.model, - messages=[ - {"role": "user", "content": [{"text": "generic-input"}]}, - {"role": "user", "content": [{"text": "user-input"}]}, - {"role": "assistant", "content": [{"text": "assistant-input"}]}, - ], - system=[{"text": "system-input"}], + messages=messages, + **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), inferenceConfig={"temperature": driver.temperature}, additionalModelRequestFields={}, ) - assert text_artifact.value == "model-output" + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py index 4ae8fe944..a75fc6ed0 100644 --- a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py @@ -2,7 +2,7 @@ from botocore.response import StreamingBody from griptape.tokenizers import HuggingFaceTokenizer from griptape.drivers.prompt.amazon_sagemaker_jumpstart_prompt_driver import AmazonSageMakerJumpstartPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack from io import BytesIO import json import pytest @@ -18,7 +18,9 @@ class TestAmazonSageMakerJumpstartPromptDriver: @pytest.fixture(autouse=True) def tokenizer(self, mocker): from_pretrained = mocker.patch("transformers.AutoTokenizer").from_pretrained - from_pretrained.return_value.apply_chat_template.return_value = "foo\n\nUser: bar" + from_pretrained.return_value.decode.return_value = "foo\n\nUser: bar" + from_pretrained.return_value.apply_chat_template.return_value = [1, 2, 3] + from_pretrained.return_value.encode.return_value = [1, 2, 3] from_pretrained.return_value.model_max_length = 8000 from_pretrained.return_value.eos_token_id = 1 @@ -35,7 +37,7 @@ def test_try_run(self, mock_client): # Given driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") + prompt_stack.add_user_message("prompt-stack") # When response_body = [{"generated_text": "foobar"}] @@ -64,6 +66,8 @@ def test_try_run(self, mock_client): ) assert text_artifact.value == "foobar" + assert text_artifact.usage.input_tokens == 3 + assert text_artifact.usage.output_tokens == 3 # When response_body = {"generated_text": "foobar"} @@ -97,7 +101,7 @@ def test_try_stream(self, mock_client): # Given driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") + prompt_stack.add_user_message("prompt-stack") # When with pytest.raises(NotImplementedError) as e: @@ -122,7 +126,7 @@ def test_try_run_throws_on_empty_response(self, mock_client): driver = AmazonSageMakerJumpstartPromptDriver(endpoint="model", model="model") mock_client.invoke_endpoint.return_value = {"Body": to_streaming_body([])} prompt_stack = PromptStack() - prompt_stack.add_user_input("prompt-stack") + prompt_stack.add_user_message("prompt-stack") # When with pytest.raises(Exception) as e: diff --git a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py index 22178bbf3..858c05ee6 100644 --- a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py @@ -1,5 +1,6 @@ from griptape.drivers import AnthropicPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.artifacts import TextArtifact, ImageArtifact, ListArtifact from unittest.mock import Mock import pytest @@ -8,21 +9,36 @@ class TestAnthropicPromptDriver: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("anthropic.Anthropic") - mock_content = Mock() - mock_content.text = "model-output" - mock_client.return_value.messages.create.return_value.content = [mock_content] - mock_client.return_value.count_tokens.return_value = 5 + + mock_client.return_value = Mock( + messages=Mock( + create=Mock( + return_value=Mock( + usage=Mock(input_tokens=5, output_tokens=10), content=[Mock(type="text", text="model-output")] + ) + ) + ) + ) return mock_client @pytest.fixture def mock_stream_client(self, mocker): mock_stream_client = mocker.patch("anthropic.Anthropic") - mock_chunk = Mock() - mock_chunk.type = "content_block_delta" - mock_chunk.delta.text = "model-output" - mock_stream_client.return_value.messages.create.return_value = iter([mock_chunk]) - mock_stream_client.return_value.count_tokens.return_value = 5 + + mock_stream_client.return_value = Mock( + messages=Mock( + create=Mock( + return_value=iter( + [ + Mock(type="message_start", message=Mock(usage=Mock(input_tokens=5))), + Mock(type="content_block_delta", delta=Mock(type="text_delta", text="model-output")), + Mock(type="message_delta", usage=Mock(output_tokens=10)), + ] + ) + ) + ) + ) return mock_stream_client @@ -45,20 +61,30 @@ def test_init(self, model): def test_try_run(self, mock_client, model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") if system_enabled: - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") driver = AnthropicPromptDriver(model=model, api_key="api-key") expected_messages = [ - {"role": "user", "content": "generic-input"}, {"role": "user", "content": "user-input"}, + {"role": "user", "content": "user-input"}, + { + "content": [ + { + "source": {"data": "aW1hZ2UtZGF0YQ==", "media_type": "image/png", "type": "base64"}, + "type": "image", + } + ], + "role": "user", + }, {"role": "assistant", "content": "assistant-input"}, ] # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_client.return_value.messages.create.assert_called_once_with( @@ -71,7 +97,9 @@ def test_try_run(self, mock_client, model, system_enabled): top_k=250, **{"system": "system-input"} if system_enabled else {}, ) - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 5 + assert message.usage.output_tokens == 10 @pytest.mark.parametrize( "model", @@ -88,20 +116,34 @@ def test_try_run(self, mock_client, model, system_enabled): def test_try_stream_run(self, mock_stream_client, model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") if system_enabled: - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") expected_messages = [ - {"role": "user", "content": "generic-input"}, {"role": "user", "content": "user-input"}, + { + "content": [ + {"type": "text", "text": "user-input"}, + { + "source": {"data": "aW1hZ2UtZGF0YQ==", "media_type": "image/png", "type": "base64"}, + "type": "image", + }, + ], + "role": "user", + }, {"role": "assistant", "content": "assistant-input"}, ] driver = AnthropicPromptDriver(model=model, api_key="api-key", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_stream_client.return_value.messages.create.assert_called_once_with( @@ -115,7 +157,13 @@ def test_try_stream_run(self, mock_stream_client, model, system_enabled): top_k=250, **{"system": "system-input"} if system_enabled else {}, ) - assert text_artifact.value == "model-output" + assert event.usage.input_tokens == 5 + + event = next(stream) + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.output_tokens == 10 def test_try_run_throws_when_prompt_stack_is_string(self): # Given @@ -127,4 +175,4 @@ def test_try_run_throws_when_prompt_stack_is_string(self): driver.try_run(prompt_stack) # pyright: ignore # Then - assert e.value.args[0] == "'str' object has no attribute 'inputs'" + assert e.value.args[0] == "'str' object has no attribute 'messages'" diff --git a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py index f6bd12d80..378ecc3da 100644 --- a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py @@ -8,20 +8,22 @@ class TestAzureOpenAiChatPromptDriver(TestOpenAiChatPromptDriverFixtureMixin): @pytest.fixture def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create - mock_choice = Mock() - mock_choice.message.content = "model-output" - mock_chat_create.return_value.headers = {} - mock_chat_create.return_value.choices = [mock_choice] + mock_chat_create.return_value = Mock( + headers={}, + choices=[Mock(message=Mock(content="model-output"))], + usage=Mock(prompt_tokens=5, completion_tokens=10), + ) return mock_chat_create @pytest.fixture def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create - mock_chunk = Mock() - mock_choice = Mock() - mock_choice.delta.content = "model-output" - mock_chunk.choices = [mock_choice] - mock_chat_create.return_value = iter([mock_chunk]) + mock_chat_create.return_value = iter( + [ + Mock(choices=[Mock(delta=Mock(content="model-output"))], usage=None), + Mock(choices=None, usage=Mock(prompt_tokens=5, completion_tokens=10)), + ] + ) return mock_chat_create def test_init(self): @@ -37,13 +39,11 @@ def test_try_run(self, mock_chat_completion_create, prompt_stack, messages): # Then mock_chat_completion_create.assert_called_once_with( - model=driver.model, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - messages=messages, + model=driver.model, temperature=driver.temperature, user=driver.user, messages=messages ) assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages): # Given @@ -52,15 +52,16 @@ def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, ) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_chat_completion_stream_create.assert_called_once_with( - model=driver.model, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - stream=True, - messages=messages, + model=driver.model, temperature=driver.temperature, user=driver.user, stream=True, messages=messages ) - assert text_artifact.value == "model-output" + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_base_prompt_driver.py b/tests/unit/drivers/prompt/test_base_prompt_driver.py index 0743402aa..6eb000e1f 100644 --- a/tests/unit/drivers/prompt/test_base_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_base_prompt_driver.py @@ -1,5 +1,6 @@ +from griptape.common.prompt_stack.messages.message import Message from griptape.events import FinishPromptEvent, StartPromptEvent -from griptape.utils import PromptStack +from griptape.common import PromptStack from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_failing_prompt_driver import MockFailingPromptDriver from griptape.artifacts import ErrorArtifact, TextArtifact @@ -37,7 +38,13 @@ def test_run_via_pipeline_publishes_events(self, mocker): assert instance_count(events, FinishPromptEvent) == 1 def test_run(self): - assert isinstance(MockPromptDriver().run(PromptStack(inputs=[])), TextArtifact) + assert isinstance(MockPromptDriver().run(PromptStack(messages=[])), Message) + + def test_run_with_stream(self): + pipeline = Pipeline() + result = MockPromptDriver(stream=True, structure=pipeline).run(PromptStack(messages=[])) + assert isinstance(result, Message) + assert result.value == "mock output" def instance_count(instances, clazz): diff --git a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py index b3ceb11a4..d65775e8b 100644 --- a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py @@ -1,22 +1,30 @@ -from griptape.drivers import CoherePromptDriver -from griptape.utils import PromptStack from unittest.mock import Mock + import pytest +from griptape.common import PromptStack +from griptape.drivers import CoherePromptDriver + class TestCoherePromptDriver: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value - mock_client.chat.return_value = Mock(text="model-output") + mock_client.chat.return_value = Mock( + text="model-output", meta=Mock(tokens=Mock(input_tokens=5, output_tokens=10)) + ) return mock_client @pytest.fixture def mock_stream_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value - mock_chunk = Mock(text="model-output", event_type="text-generation") - mock_client.chat_stream.return_value = iter([mock_chunk]) + mock_client.chat_stream.return_value = iter( + [ + Mock(text="model-output", event_type="text-generation"), + Mock(response=Mock(meta=Mock(tokens=Mock(input_tokens=5, output_tokens=10))), event_type="stream-end"), + ] + ) return mock_client @@ -24,19 +32,21 @@ def mock_stream_client(self, mocker): def mock_tokenizer(self, mocker): return mocker.patch("griptape.tokenizers.CohereTokenizer").return_value - @pytest.fixture - def prompt_stack(self): + @pytest.fixture(params=[True, False]) + def prompt_stack(self, request): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + if request.param: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") return prompt_stack def test_init(self): assert CoherePromptDriver(model="command", api_key="foobar") - def test_try_run(self, mock_client, prompt_stack): # pyright: ignore + def test_try_run(self, mock_client, prompt_stack): # Given driver = CoherePromptDriver(model="command", api_key="api-key") @@ -44,14 +54,48 @@ def test_try_run(self, mock_client, prompt_stack): # pyright: ignore text_artifact = driver.try_run(prompt_stack) # Then + mock_client.chat.assert_called_once_with( + chat_history=[ + {"content": [{"text": "user-input"}], "role": "USER"}, + {"content": [{"text": "assistant-input"}], "role": "CHATBOT"}, + {"content": [{"text": "user-input"}], "role": "USER"}, + ], + max_tokens=None, + message="assistant-input", + **({"preamble": "system-input"} if prompt_stack.system_messages else {}), + stop_sequences=[], + temperature=0.1, + ) + assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 def test_try_stream_run(self, mock_stream_client, prompt_stack): # pyright: ignore # Given driver = CoherePromptDriver(model="command", api_key="api-key", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then - assert text_artifact.value == "model-output" + + mock_stream_client.chat_stream.assert_called_once_with( + chat_history=[ + {"content": [{"text": "user-input"}], "role": "USER"}, + {"content": [{"text": "assistant-input"}], "role": "CHATBOT"}, + {"content": [{"text": "user-input"}], "role": "USER"}, + ], + max_tokens=None, + message="assistant-input", + **({"preamble": "system-input"} if prompt_stack.system_messages else {}), + stop_sequences=[], + temperature=0.1, + ) + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_google_prompt_driver.py b/tests/unit/drivers/prompt/test_google_prompt_driver.py index f655d3e51..6a25ec3d3 100644 --- a/tests/unit/drivers/prompt/test_google_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_google_prompt_driver.py @@ -1,6 +1,7 @@ from google.generativeai.types import GenerationConfig +from griptape.artifacts import TextArtifact, ImageArtifact from griptape.drivers import GooglePromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack from unittest.mock import Mock import pytest @@ -9,14 +10,21 @@ class TestGooglePromptDriver: @pytest.fixture def mock_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") - mock_generative_model.return_value.generate_content.return_value = Mock(text="model-output") + mock_generative_model.return_value.generate_content.return_value = Mock( + text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=10) + ) return mock_generative_model @pytest.fixture def mock_stream_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") - mock_generative_model.return_value.generate_content.return_value = iter([Mock(text="model-output")]) + mock_generative_model.return_value.generate_content.return_value = iter( + [ + Mock(text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5)), + Mock(text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5)), + ] + ) return mock_generative_model @@ -24,75 +32,77 @@ def test_init(self): driver = GooglePromptDriver(model="gemini-pro", api_key="1234") assert driver - def test_try_run(self, mock_generative_model): + @pytest.mark.parametrize("system_enabled", [True, False]) + def test_try_run(self, mock_generative_model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_generic_input("generic-input") + if system_enabled: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", top_p=0.5, top_k=50) # When text_artifact = driver.try_run(prompt_stack) # Then + messages = [ + *( + [{"parts": ["system-input", "user-input"], "role": "user"}] + if system_enabled + else [{"parts": ["user-input"], "role": "user"}] + ), + {"parts": ["user-input"], "role": "user"}, + {"parts": [{"data": b"image-data", "mime_type": "image/png"}], "role": "user"}, + {"parts": ["assistant-input"], "role": "model"}, + ] mock_generative_model.return_value.generate_content.assert_called_once_with( - [ - {"parts": ["system-input", "user-input"], "role": "user"}, - {"parts": ["assistant-input"], "role": "model"}, - {"parts": ["generic-input"], "role": "user"}, - ], + messages, generation_config=GenerationConfig( max_output_tokens=None, temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[] ), ) assert text_artifact.value == "model-output" + assert text_artifact.usage.input_tokens == 5 + assert text_artifact.usage.output_tokens == 10 - def test_try_stream(self, mock_stream_generative_model): + @pytest.mark.parametrize("system_enabled", [True, False]) + def test_try_stream(self, mock_stream_generative_model, system_enabled): # Given prompt_stack = PromptStack() - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_generic_input("generic-input") + if system_enabled: + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message(TextArtifact("user-input")) + prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_assistant_message("assistant-input") driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", stream=True, top_p=0.5, top_k=50) # When - text_artifact_stream = driver.try_stream(prompt_stack) + stream = driver.try_stream(prompt_stack) # Then - text_artifact = next(text_artifact_stream) + event = next(stream) + messages = [ + *( + [{"parts": ["system-input", "user-input"], "role": "user"}] + if system_enabled + else [{"parts": ["user-input"], "role": "user"}] + ), + {"parts": ["user-input"], "role": "user"}, + {"parts": [{"data": b"image-data", "mime_type": "image/png"}], "role": "user"}, + {"parts": ["assistant-input"], "role": "model"}, + ] mock_stream_generative_model.return_value.generate_content.assert_called_once_with( - [ - {"parts": ["system-input", "user-input"], "role": "user"}, - {"parts": ["assistant-input"], "role": "model"}, - {"parts": ["generic-input"], "role": "user"}, - ], + messages, stream=True, generation_config=GenerationConfig(temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[]), ) - assert text_artifact.value == "model-output" - - def test_prompt_stack_to_model_input(self): - # Given - driver = GooglePromptDriver(model="gemini-pro", api_key="1234") - prompt_stack = PromptStack() - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_assistant_input("assistant-input") - prompt_stack.add_user_input("user-input") + assert event.content.text == "model-output" + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 5 - # When - model_input = driver._prompt_stack_to_model_input(prompt_stack) - - # Then - assert model_input == [ - {"role": "user", "parts": ["system-input", "user-input"]}, - {"role": "model", "parts": ["assistant-input"]}, - {"role": "user", "parts": ["generic-input"]}, - {"role": "model", "parts": ["assistant-input"]}, - {"role": "user", "parts": ["user-input"]}, - ] + event = next(stream) + assert event.usage.output_tokens == 5 diff --git a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py index 15bbb4ead..4618e1de3 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py @@ -1,5 +1,5 @@ from griptape.drivers import HuggingFaceHubPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack import pytest @@ -7,6 +7,7 @@ class TestHuggingFaceHubPromptDriver: @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("huggingface_hub.InferenceClient").return_value + mock_client.text_generation.return_value = "model-output" return mock_client @@ -14,6 +15,8 @@ def mock_client(self, mocker): def tokenizer(self, mocker): from_pretrained = tokenizer = mocker.patch("transformers.AutoTokenizer").from_pretrained from_pretrained.return_value.apply_chat_template.return_value = [1, 2, 3] + from_pretrained.return_value.decode.return_value = "foo\n\nUser: bar" + from_pretrained.return_value.encode.return_value = [1, 2, 3] return tokenizer @@ -27,10 +30,9 @@ def mock_client_stream(self, mocker): @pytest.fixture def prompt_stack(self): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") return prompt_stack @pytest.fixture(autouse=True) @@ -47,17 +49,24 @@ def test_try_run(self, prompt_stack, mock_client): driver = HuggingFaceHubPromptDriver(api_token="api-token", model="repo-id") # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 3 + assert message.usage.output_tokens == 3 def test_try_stream(self, prompt_stack, mock_client_stream): # Given driver = HuggingFaceHubPromptDriver(api_token="api-token", model="repo-id", stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then - assert text_artifact.value == "model-output" + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 3 + assert event.usage.output_tokens == 3 diff --git a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py index b2746ca58..a63d697fb 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py @@ -1,5 +1,5 @@ from griptape.drivers import HuggingFacePipelinePromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack import pytest @@ -22,15 +22,15 @@ def mock_autotokenizer(self, mocker): mock_autotokenizer.model_max_length = 42 mock_autotokenizer.apply_chat_template.return_value = [1, 2, 3] mock_autotokenizer.decode.return_value = "model-output" + mock_autotokenizer.encode.return_value = [1, 2, 3] return mock_autotokenizer @pytest.fixture def prompt_stack(self): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_assistant_message("assistant-input") return prompt_stack def test_init(self): @@ -41,10 +41,12 @@ def test_try_run(self, prompt_stack): driver = HuggingFacePipelinePromptDriver(model="foo", max_tokens=42) # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 3 + assert message.usage.output_tokens == 3 def test_try_stream(self, prompt_stack): # Given diff --git a/tests/unit/drivers/prompt/test_ollama_prompt_driver.py b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py index d42a8b45d..a247a77ab 100644 --- a/tests/unit/drivers/prompt/test_ollama_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py @@ -1,5 +1,7 @@ +from griptape.common.prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent from griptape.drivers import OllamaPromptDriver -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact import pytest @@ -25,20 +27,24 @@ def test_init(self): def test_try_run(self, mock_client): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") driver = OllamaPromptDriver(model="llama") expected_messages = [ - {"role": "generic", "content": "generic-input"}, {"role": "system", "content": "system-input"}, {"role": "user", "content": "user-input"}, + {"role": "user", "content": "user-input", "images": ["aW1hZ2UtZGF0YQ=="]}, {"role": "assistant", "content": "assistant-input"}, ] # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_client.return_value.chat.assert_called_once_with( @@ -46,7 +52,9 @@ def test_try_run(self, mock_client): model=driver.model, options={"temperature": driver.temperature, "stop": [], "num_predict": driver.max_tokens}, ) - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens is None + assert message.usage.output_tokens is None def test_try_run_bad_response(self, mock_client): # Given @@ -61,14 +69,18 @@ def test_try_run_bad_response(self, mock_client): def test_try_stream_run(self, mock_stream_client): # Given prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") expected_messages = [ - {"role": "generic", "content": "generic-input"}, {"role": "system", "content": "system-input"}, {"role": "user", "content": "user-input"}, + {"role": "user", "content": "user-input", "images": ["aW1hZ2UtZGF0YQ=="]}, {"role": "assistant", "content": "assistant-input"}, ] driver = OllamaPromptDriver(model="llama", stream=True) @@ -83,7 +95,8 @@ def test_try_stream_run(self, mock_stream_client): options={"temperature": driver.temperature, "stop": [], "num_predict": driver.max_tokens}, stream=True, ) - assert text_artifact.value == "model-output" + if isinstance(text_artifact, TextDeltaMessageContent): + assert text_artifact.text == "model-output" def test_try_stream_bad_response(self, mock_stream_client): # Given diff --git a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py index a2900d4d3..5c217ed06 100644 --- a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py @@ -1,8 +1,10 @@ +from griptape.artifacts import ImageArtifact, ListArtifact +from griptape.artifacts import TextArtifact from griptape.drivers import OpenAiChatPromptDriver -from griptape.tokenizers.huggingface_tokenizer import HuggingFaceTokenizer -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.tokenizers import OpenAiTokenizer from unittest.mock import Mock +from tests.mocks.mock_tokenizer import MockTokenizer import pytest @@ -10,37 +12,51 @@ class TestOpenAiChatPromptDriverFixtureMixin: @pytest.fixture def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create - mock_choice = Mock() - mock_choice.message.content = "model-output" - mock_chat_create.return_value.headers = {} - mock_chat_create.return_value.choices = [mock_choice] + mock_chat_create.return_value = Mock( + headers={}, + choices=[Mock(message=Mock(content="model-output"))], + usage=Mock(prompt_tokens=5, completion_tokens=10), + ) + return mock_chat_create @pytest.fixture def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create - mock_chunk = Mock() - mock_choice = Mock() - mock_choice.delta.content = "model-output" - mock_chunk.choices = [mock_choice] - mock_chat_create.return_value = iter([mock_chunk]) + mock_chat_create.return_value = iter( + [ + Mock(choices=[Mock(delta=Mock(content="model-output"))], usage=None), + Mock(choices=None, usage=Mock(prompt_tokens=5, completion_tokens=10)), + Mock(choices=[Mock(delta=Mock(content=None))], usage=None), + ] + ) return mock_chat_create @pytest.fixture def prompt_stack(self): prompt_stack = PromptStack() - prompt_stack.add_generic_input("generic-input") - prompt_stack.add_system_input("system-input") - prompt_stack.add_user_input("user-input") - prompt_stack.add_assistant_input("assistant-input") + prompt_stack.add_system_message("system-input") + prompt_stack.add_user_message("user-input") + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) + prompt_stack.add_assistant_message("assistant-input") return prompt_stack @pytest.fixture def messages(self): return [ - {"role": "user", "content": "generic-input"}, {"role": "system", "content": "system-input"}, {"role": "user", "content": "user-input"}, + { + "role": "user", + "content": [ + {"type": "text", "text": "user-input"}, + {"type": "image_url", "image_url": {"url": "data:image/png;base64,aW1hZ2UtZGF0YQ=="}}, + ], + }, {"role": "assistant", "content": "assistant-input"}, ] @@ -87,18 +103,13 @@ def test_try_run(self, mock_chat_completion_create, prompt_stack, messages): driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) # When - text_artifact = driver.try_run(prompt_stack) + event = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( - model=driver.model, - temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, - user=driver.user, - messages=messages, - seed=driver.seed, + model=driver.model, temperature=driver.temperature, user=driver.user, messages=messages, seed=driver.seed ) - assert text_artifact.value == "model-output" + assert event.value == "model-output" def test_try_run_response_format(self, mock_chat_completion_create, prompt_stack, messages): # Given @@ -107,57 +118,65 @@ def test_try_run_response_format(self, mock_chat_completion_create, prompt_stack ) # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( model=driver.model, temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, user=driver.user, messages=[*messages, {"role": "system", "content": "Provide your response as a valid JSON object."}], seed=driver.seed, response_format={"type": "json_object"}, ) - assert text_artifact.value == "model-output" + assert message.value == "model-output" + assert message.usage.input_tokens == 5 + assert message.usage.output_tokens == 10 def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, stream=True) # When - text_artifact = next(driver.try_stream(prompt_stack)) + stream = driver.try_stream(prompt_stack) + event = next(stream) # Then mock_chat_completion_stream_create.assert_called_once_with( model=driver.model, temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, user=driver.user, stream=True, messages=messages, seed=driver.seed, + stream_options={"include_usage": True}, ) - assert text_artifact.value == "model-output" + + assert event.content.text == "model-output" + + event = next(stream) + assert event.usage.input_tokens == 5 + assert event.usage.output_tokens == 10 + event = next(stream) + assert event.content.text == "" def test_try_run_with_max_tokens(self, mock_chat_completion_create, prompt_stack, messages): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, max_tokens=1) # When - text_artifact = driver.try_run(prompt_stack) + event = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( model=driver.model, temperature=driver.temperature, - stop=driver.tokenizer.stop_sequences, user=driver.user, messages=messages, max_tokens=1, seed=driver.seed, ) - assert text_artifact.value == "model-output" + assert event.value == "model-output" def test_try_run_throws_when_prompt_stack_is_string(self): # Given @@ -168,30 +187,29 @@ def test_try_run_throws_when_prompt_stack_is_string(self): driver.try_run("prompt-stack") # pyright: ignore # Then - assert e.value.args[0] == "'str' object has no attribute 'inputs'" + assert e.value.args[0] == "'str' object has no attribute 'messages'" - @pytest.mark.parametrize("choices", [[], [1, 2]]) - def test_try_run_throws_when_multiple_choices_returned(self, choices, mock_chat_completion_create, prompt_stack): + def test_try_run_throws_when_multiple_choices_returned(self, mock_chat_completion_create, prompt_stack): # Given driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, api_key="api-key") - mock_chat_completion_create.return_value.choices = [choices] + mock_chat_completion_create.return_value.choices = [Mock(message=Mock(content="model-output"))] * 10 # When with pytest.raises(Exception) as e: driver.try_run(prompt_stack) # Then - e.value.args[0] == "Completion with more than one choice is not supported yet." + assert e.value.args[0] == "Completion with more than one choice is not supported yet." def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messages): driver = OpenAiChatPromptDriver( model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, - tokenizer=HuggingFaceTokenizer(model="gpt2", max_output_tokens=1000), + tokenizer=MockTokenizer(model="mock-model", stop_sequences=["mock-stop"]), max_tokens=1, ) # When - text_artifact = driver.try_run(prompt_stack) + event = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( @@ -199,13 +217,8 @@ def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messa temperature=driver.temperature, stop=driver.tokenizer.stop_sequences, user=driver.user, - messages=[ - {"role": "user", "content": "generic-input"}, - {"role": "system", "content": "system-input"}, - {"role": "user", "content": "user-input"}, - {"role": "assistant", "content": "assistant-input"}, - ], + messages=messages, seed=driver.seed, max_tokens=1, ) - assert text_artifact.value == "model-output" + assert event.value == "model-output" diff --git a/tests/unit/drivers/rerank/__init__.py b/tests/unit/drivers/rerank/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/drivers/rerank/test_cohere_rerank_driver.py b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py new file mode 100644 index 000000000..952546e5a --- /dev/null +++ b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py @@ -0,0 +1,26 @@ +import pytest +from cohere import RerankResponseResultsItemDocument, RerankResponseResultsItem +from griptape.artifacts import TextArtifact +from griptape.drivers import CohereRerankDriver + + +class TestCohereRerankDriver: + @pytest.fixture + def mock_client(self, mocker): + mock_client = mocker.patch("cohere.Client").return_value + mock_client.rerank.return_value.results = [ + RerankResponseResultsItem( + index=1, relevance_score=1.0, document=RerankResponseResultsItemDocument(text="foo") + ), + RerankResponseResultsItem( + index=2, relevance_score=0.5, document=RerankResponseResultsItemDocument(text="bar") + ), + ] + + return mock_client + + def test_run(self, mock_client): + driver = CohereRerankDriver(api_key="api-key") + result = driver.run("hello", artifacts=[TextArtifact("foo"), TextArtifact("bar")]) + + assert len(result) == 2 diff --git a/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py b/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py index 53fce635e..b68486914 100644 --- a/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py @@ -40,8 +40,8 @@ def test_upsert_text(self, driver): def test_query(self, driver, monkeypatch): mock_query_result = [ - BaseVectorStoreDriver.QueryResult("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), - BaseVectorStoreDriver.QueryResult("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), ] monkeypatch.setattr(AzureMongoDbVectorStoreDriver, "query", lambda *args, **kwargs: mock_query_result) @@ -52,7 +52,7 @@ def test_query(self, driver, monkeypatch): for result, expected in zip(results, mock_query_result): assert result.id == expected.id assert result.vector == expected.vector - assert isinstance(result, BaseVectorStoreDriver.QueryResult) + assert isinstance(result, BaseVectorStoreDriver.Entry) def test_load_entry(self, driver): vector_id_str = "123" diff --git a/tests/unit/drivers/vector/test_base_local_vector_store_driver.py b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py new file mode 100644 index 000000000..6cd1763f6 --- /dev/null +++ b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py @@ -0,0 +1,87 @@ +from abc import ABC, abstractmethod +import pytest +from unittest.mock import patch +from griptape.artifacts import TextArtifact +from griptape.artifacts.csv_row_artifact import CsvRowArtifact + + +class BaseLocalVectorStoreDriver(ABC): + @pytest.fixture + @abstractmethod + def driver(self): ... + + def test_upsert(self, driver): + namespace = driver.upsert_text_artifact(TextArtifact(id="foo1", value="foobar")) + + assert len(driver.entries) == 1 + assert list(driver.entries.keys())[0] == namespace + + driver.upsert_text_artifact(TextArtifact(id="foo1", value="foobar")) + + assert len(driver.entries) == 1 + + driver.upsert_text_artifact(TextArtifact(id="foo2", value="foobar2")) + + assert len(driver.entries) == 2 + + def test_upsert_csv_row(self, driver): + namespace = driver.upsert_text_artifact(CsvRowArtifact(id="foo1", value={"col": "value"})) + + assert len(driver.entries) == 1 + assert list(driver.entries.keys())[0] == namespace + + driver.upsert_text_artifact(CsvRowArtifact(id="foo1", value={"col": "value"})) + + assert len(driver.entries) == 1 + + driver.upsert_text_artifact(CsvRowArtifact(id="foo2", value={"col": "value2"})) + + assert len(driver.entries) == 2 + + def test_upsert_multiple(self, driver): + driver.upsert_text_artifacts({"foo": [TextArtifact("foo")], "bar": [TextArtifact("bar")]}) + + foo_entries = driver.load_entries("foo") + bar_entries = driver.load_entries("bar") + + assert len(driver.entries) == 2 + assert foo_entries[0].to_artifact().value == "foo" + assert bar_entries[0].to_artifact().value == "bar" + + def test_query(self, driver): + vector_id = driver.upsert_text_artifact(TextArtifact("foobar"), namespace="test-namespace") + + assert len(driver.query("foobar")) == 1 + assert len(driver.query("foobar", namespace="bad-namespace")) == 0 + assert len(driver.query("foobar", namespace="test-namespace")) == 1 + assert driver.query("foobar")[0].vector == [] + assert driver.query("foobar", include_vectors=True)[0].vector == [0, 1] + assert driver.query("foobar")[0].to_artifact().value == "foobar" + assert driver.query("foobar")[0].id == vector_id + + def test_load_entry(self, driver): + vector_id = driver.upsert_text_artifact(TextArtifact("foobar"), namespace="test-namespace") + + assert driver.load_entry(vector_id, namespace="test-namespace").id == vector_id + + def test_load_entries(self, driver): + driver.upsert_text_artifact(TextArtifact("foobar 1"), namespace="test-namespace-1") + driver.upsert_text_artifact(TextArtifact("foobar 2"), namespace="test-namespace-1") + driver.upsert_text_artifact(TextArtifact("foobar 3"), namespace="test-namespace-2") + + assert len(driver.load_entries()) == 3 + assert len(driver.load_entries("test-namespace-1")) == 2 + assert len(driver.load_entries("test-namespace-2")) == 1 + + def test_load_artifacts(self, driver): + driver.upsert_text_artifact(TextArtifact("foobar 1"), namespace="test-namespace-1") + driver.upsert_text_artifact(TextArtifact("foobar 2"), namespace="test-namespace-1") + driver.upsert_text_artifact(TextArtifact("foobar 3"), namespace="test-namespace-2") + + assert len(driver.load_artifacts()) == 3 + assert len(driver.load_artifacts("test-namespace-1")) == 2 + assert len(driver.load_artifacts("test-namespace-2")) == 1 + + def test_does_entry_exist_exception(self, driver): + with patch.object(driver, "load_entry", side_effect=Exception): + assert driver.does_entry_exist("does_not_exist") is False diff --git a/tests/unit/drivers/vector/test_entry.py b/tests/unit/drivers/vector/test_entry.py new file mode 100644 index 000000000..56ee468e1 --- /dev/null +++ b/tests/unit/drivers/vector/test_entry.py @@ -0,0 +1,12 @@ +from griptape.artifacts import TextArtifact +from griptape.drivers import BaseVectorStoreDriver + + +class TestEntry: + def test_from_dict(self): + entry_dict = {"id": "test", "vector": [], "meta": {"artifact": TextArtifact("foo").to_json()}} + assert BaseVectorStoreDriver.Entry.from_dict(entry_dict).id == "test" + + def test_to_artifact(self): + entry = BaseVectorStoreDriver.Entry(id="test", vector=[], meta={"artifact": TextArtifact("foo").to_json()}) + assert entry.to_artifact().value == "foo" diff --git a/tests/unit/drivers/vector/test_local_vector_store_driver.py b/tests/unit/drivers/vector/test_local_vector_store_driver.py index 8def2c94f..937f14ece 100644 --- a/tests/unit/drivers/vector/test_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_local_vector_store_driver.py @@ -1,55 +1,23 @@ import pytest -from griptape.artifacts import TextArtifact, BaseArtifact +from griptape.artifacts import TextArtifact from griptape.drivers import LocalVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.unit.drivers.vector.test_base_local_vector_store_driver import BaseLocalVectorStoreDriver -class TestLocalVectorStoreDriver: +class TestLocalVectorStoreDriver(BaseLocalVectorStoreDriver): @pytest.fixture def driver(self): return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) - def test_upsert(self, driver): - namespace = driver.upsert_text_artifact(TextArtifact("foobar")) + def test_upsert_text_artifacts_dict(self, driver): + driver.upsert_text_artifacts({"foo": [TextArtifact("bar"), TextArtifact("baz")], "bar": [TextArtifact("bar")]}) - assert len(driver.entries) == 1 - assert list(driver.entries.keys())[0] == namespace + assert len(driver.load_artifacts("foo")) == 2 + assert len(driver.load_artifacts("bar")) == 1 - driver.upsert_text_artifact(TextArtifact("foobar")) + def test_upsert_text_artifacts_list(self, driver): + driver.upsert_text_artifacts([TextArtifact("bar"), TextArtifact("baz")]) - assert len(driver.entries) == 2 - - def test_upsert_multiple(self, driver): - driver.upsert_text_artifacts({"foo": [TextArtifact("foo")], "bar": [TextArtifact("bar")]}) - - foo_entries = driver.load_entries("foo") - bar_entries = driver.load_entries("bar") - - assert len(driver.entries) == 2 - assert BaseArtifact.from_json(foo_entries[0].meta["artifact"]).value == "foo" - assert BaseArtifact.from_json(bar_entries[0].meta["artifact"]).value == "bar" - - def test_query(self, driver): - vector_id = driver.upsert_text_artifact(TextArtifact("foobar"), namespace="test-namespace") - - assert len(driver.query("foobar")) == 1 - assert len(driver.query("foobar", namespace="bad-namespace")) == 0 - assert len(driver.query("foobar", namespace="test-namespace")) == 1 - assert driver.query("foobar")[0].vector == [] - assert driver.query("foobar", include_vectors=True)[0].vector == [0, 1] - assert BaseArtifact.from_json(driver.query("foobar")[0].meta["artifact"]).value == "foobar" - assert driver.query("foobar")[0].id == vector_id - - def test_load_entry(self, driver): - vector_id = driver.upsert_text_artifact(TextArtifact("foobar"), namespace="test-namespace") - - assert driver.load_entry(vector_id, namespace="test-namespace").id == vector_id - - def test_load_entries(self, driver): - driver.upsert_text_artifact(TextArtifact("foobar 1"), namespace="test-namespace-1") - driver.upsert_text_artifact(TextArtifact("foobar 2"), namespace="test-namespace-1") - driver.upsert_text_artifact(TextArtifact("foobar 3"), namespace="test-namespace-2") - - assert len(driver.load_entries()) == 3 - assert len(driver.load_entries("test-namespace-1")) == 2 - assert len(driver.load_entries("test-namespace-2")) == 1 + assert len(driver.load_artifacts("foo")) == 0 + assert len(driver.load_artifacts()) == 2 diff --git a/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py b/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py index 28cddcfbc..5b9aeed06 100644 --- a/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py @@ -40,8 +40,8 @@ def test_upsert_text(self, driver): def test_query(self, driver, monkeypatch): mock_query_result = [ - BaseVectorStoreDriver.QueryResult("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), - BaseVectorStoreDriver.QueryResult("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", [0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), + BaseVectorStoreDriver.Entry("foo", vector=[0.5, 0.5, 0.5], score=0.0, meta={}, namespace=None), ] monkeypatch.setattr(MongoDbAtlasVectorStoreDriver, "query", lambda *args, **kwargs: mock_query_result) @@ -52,7 +52,7 @@ def test_query(self, driver, monkeypatch): for result, expected in zip(results, mock_query_result): assert result.id == expected.id assert result.vector == expected.vector - assert isinstance(result, BaseVectorStoreDriver.QueryResult) + assert isinstance(result, BaseVectorStoreDriver.Entry) def test_load_entry(self, driver): vector_id_str = "123" diff --git a/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py new file mode 100644 index 000000000..8f6773fc1 --- /dev/null +++ b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py @@ -0,0 +1,29 @@ +import os +import tempfile +import pytest +from griptape.artifacts import TextArtifact +from griptape.drivers import LocalVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.unit.drivers.vector.test_base_local_vector_store_driver import BaseLocalVectorStoreDriver + + +class TestPersistentLocalVectorStoreDriver(BaseLocalVectorStoreDriver): + @pytest.fixture + def temp_dir(self): + with tempfile.TemporaryDirectory() as temp_dir: + yield temp_dir + + @pytest.fixture + def driver(self, temp_dir): + persist_file = os.path.join(temp_dir, "store.json") + + return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver(), persist_file=persist_file) + + def test_persistence(self, driver, temp_dir): + persist_file = os.path.join(temp_dir, "store.json") + + driver.upsert_text_artifact(TextArtifact("persistent foobar")) + + new_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver(), persist_file=persist_file) + + assert new_driver.query("persistent foobar")[0].to_artifact().value == "persistent foobar" diff --git a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py index defbe8e3b..7aea4d411 100644 --- a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py +++ b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py @@ -1,4 +1,6 @@ import pytest + +from griptape import utils from griptape.artifacts import TextArtifact from griptape.drivers import PineconeVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -32,7 +34,7 @@ def driver(self): def test_upsert_text_artifact(self, driver): artifact = TextArtifact("foo") - assert driver.upsert_text_artifact(artifact) == artifact.id + assert driver.upsert_text_artifact(artifact) == driver._get_default_vector_id("foo") def test_upsert_vector(self, driver): assert driver.upsert_vector([0, 1, 2], vector_id="foo") == "foo" diff --git a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py new file mode 100644 index 000000000..c999af8b9 --- /dev/null +++ b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py @@ -0,0 +1,172 @@ +import pytest +from unittest.mock import MagicMock, patch +from griptape.drivers import QdrantVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from griptape.utils import import_optional_dependency +import uuid + + +class TestQdrantVectorStoreDriver: + @pytest.fixture + def embedding_driver(self): + return MockEmbeddingDriver() + + @pytest.fixture + def mock_engine(self): + return MagicMock() + + @pytest.fixture(autouse=True) + def driver(self, embedding_driver, mocker): + mocker.patch("qdrant_client.QdrantClient") + driver = QdrantVectorStoreDriver( + url="http://some_url", + port=8080, + grpc_port=50051, + prefer_grpc=True, + api_key=None, + https=False, + prefix=None, + force_disable_check_same_thread=False, + timeout=5, + distance="COSINE", + collection_name="some_collection", + vector_name=None, + content_payload_key="data", + embedding_driver=embedding_driver, + ) + return driver + + def test_attrs_post_init(self, driver): + with patch("griptape.drivers.vector.qdrant_vector_store_driver.import_optional_dependency") as mock_import: + mock_qdrant_client = MagicMock() + mock_import.return_value.QdrantClient.return_value = mock_qdrant_client + + driver.__attrs_post_init__() + + mock_import.assert_called_once_with("qdrant_client") + mock_import.return_value.QdrantClient.assert_called_once_with( + location=driver.location, + url=driver.url, + host=driver.host, + path=driver.path, + port=driver.port, + prefer_grpc=driver.prefer_grpc, + grpc_port=driver.grpc_port, + api_key=driver.api_key, + https=driver.https, + prefix=driver.prefix, + force_disable_check_same_thread=driver.force_disable_check_same_thread, + timeout=driver.timeout, + ) + assert driver.client == mock_qdrant_client + + def test_delete_vector(self, driver): + vector_id = "test_vector_id" + + mock_deletion_response = MagicMock() + mock_deletion_response.status = import_optional_dependency("qdrant_client.http.models").UpdateStatus.COMPLETED + + with patch.object(driver.client, "delete", return_value=mock_deletion_response) as mock_delete, patch( + "griptape.drivers.vector.qdrant_vector_store_driver.import_optional_dependency" + ) as mock_import: + mock_import.return_value.PointIdsList.return_value = MagicMock() + mock_import.return_value.UpdateStatus = import_optional_dependency("qdrant_client.http.models").UpdateStatus + + driver.delete_vector(vector_id) + + mock_delete.assert_called_once_with( + collection_name=driver.collection_name, + points_selector=mock_import.return_value.PointIdsList(points=[vector_id]), + ) + + def test_query(self, driver): + mock_query_result = [ + MagicMock( + id="foo", vector=[0, 1, 0], score=42, payload={"foo": "bar", "_score": 0.99, "_tensor_facets": []} + ) + ] + + with patch.object( + driver.embedding_driver, "embed_string", return_value=[0.1, 0.2, 0.3] + ) as mock_embed, patch.object(driver.client, "search", return_value=mock_query_result) as mock_search: + query = "test" + count = 10 + include_vectors = True + + results = driver.query(query, count, include_vectors=include_vectors) + + mock_embed.assert_called_once_with(query) + mock_search.assert_called_once_with( + collection_name=driver.collection_name, query_vector=[0.1, 0.2, 0.3], limit=count + ) + + assert len(results) == 1 + assert results[0].id == "foo" + assert results[0].vector == [0, 1, 0] if include_vectors else [] + assert results[0].score == 42 + assert results[0].meta == {"foo": "bar"} + + def test_upsert_with_batch(self, driver): + vector = [0.1, 0.2, 0.3] + vector_id = str(uuid.uuid4()) + meta = {"meta_key": "meta_value"} + + with patch("griptape.drivers.vector.qdrant_vector_store_driver.import_optional_dependency") as mock_import: + mock_batch = MagicMock() + mock_import.return_value.Batch.return_value = mock_batch + mock_qdrant_client = MagicMock() + driver.client = mock_qdrant_client + + result = driver.upsert_vector(vector=vector, vector_id=vector_id, meta=meta) + + mock_import.assert_called_once_with("qdrant_client.http.models") + mock_import.return_value.Batch.assert_called_once_with(ids=[vector_id], vectors=[vector], payloads=[meta]) + driver.client.upsert.assert_called_once_with(collection_name=driver.collection_name, points=mock_batch) + assert result == vector_id + + def test_load_entry(self, driver): + vector_id = str(uuid.uuid4()) + mock_entry = MagicMock() + mock_entry.id = vector_id + mock_entry.vector = [0.1, 0.2, 0.3] + mock_entry.payload = {"meta_key": "meta_value", "_score": 0.99, "_tensor_facets": []} + + with patch.object(driver.client, "retrieve", return_value=[mock_entry]): + result = driver.load_entry(vector_id) + + driver.client.retrieve.assert_called_once_with(collection_name=driver.collection_name, ids=[vector_id]) + + assert result.id == vector_id + assert result.vector == [0.1, 0.2, 0.3] + assert result.meta == {"meta_key": "meta_value"} + + with patch.object(driver.client, "retrieve", return_value=[]): + result = driver.load_entry(vector_id) + + driver.client.retrieve.assert_called_with(collection_name=driver.collection_name, ids=[vector_id]) + assert result is None + + def test_load_entries(self, driver): + mock_entries = [ + MagicMock( + id="id1", vector=[0.1, 0.2, 0.3], payload={"key1": "value1", "_score": 0.99, "_tensor_facets": []} + ), + MagicMock( + id="id2", vector=[0.4, 0.5, 0.6], payload={"key2": "value2", "_score": 0.88, "_tensor_facets": []} + ), + ] + + with patch.object(driver.client, "retrieve", return_value=mock_entries) as mock_retrieve: + results = driver.load_entries(ids=["id1", "id2"], with_payload=True, with_vectors=True) + + mock_retrieve.assert_called_once_with( + collection_name=driver.collection_name, ids=["id1", "id2"], with_payload=True, with_vectors=True + ) + + assert len(results) == 2 + assert results[0].id == "id1" + assert results[0].vector == [0.1, 0.2, 0.3] + assert results[0].meta == {"key1": "value1"} + assert results[1].id == "id2" + assert results[1].vector == [0.4, 0.5, 0.6] + assert results[1].meta == {"key2": "value2"} diff --git a/tests/unit/drivers/vector/test_redis_vector_store_driver.py b/tests/unit/drivers/vector/test_redis_vector_store_driver.py index 3c98180e7..18759a2d7 100644 --- a/tests/unit/drivers/vector/test_redis_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_redis_vector_store_driver.py @@ -1,6 +1,5 @@ from unittest.mock import MagicMock import pytest -import redis from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from griptape.drivers import RedisVectorStoreDriver diff --git a/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py b/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py new file mode 100644 index 000000000..569800c6a --- /dev/null +++ b/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py @@ -0,0 +1,34 @@ +import pytest + +from griptape.drivers import ProxyWebScraperDriver +from griptape.artifacts import TextArtifact + + +class TestProxyWebScraperDriver: + @pytest.fixture(autouse=True) + def mock_client(self, mocker): + mock_response = mocker.Mock() + mock_response.text = "test_scrape" + return mocker.patch("requests.get", return_value=mock_response) + + @pytest.fixture + def mock_client_error(self, mocker): + return mocker.patch("requests.get", side_effect=Exception("test_error")) + + @pytest.fixture + def web_scraper(self, mocker): + return ProxyWebScraperDriver( + proxies={"http": "http://localhost:8080", "https": "http://localhost:8080"}, + params={"test_param": "test_param"}, + ) + + def test_scrape_url(self, web_scraper, mock_client): + output = web_scraper.scrape_url("https://example.com/") + mock_client.assert_called_with("https://example.com/", proxies=web_scraper.proxies, test_param="test_param") + assert isinstance(output, TextArtifact) + assert "test_scrape" == output.value + + def test_scrape_url_error(self, web_scraper, mock_client_error): + with pytest.raises(Exception, match="test_error"): + web_scraper.scrape_url("https://example.com/") + assert mock_client_error.called diff --git a/tests/unit/drivers/web_search/__init__.py b/tests/unit/drivers/web_search/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py b/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py new file mode 100644 index 000000000..fcacc274c --- /dev/null +++ b/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py @@ -0,0 +1,36 @@ +import pytest +import json +from griptape.drivers import DuckDuckGoWebSearchDriver +from griptape.artifacts import ListArtifact + + +class TestDuckDuckGoWebSearchDriver: + @pytest.fixture + def driver(self, mocker): + mock_response = [ + {"title": "foo", "href": "bar", "body": "baz"}, + {"title": "foo2", "href": "bar2", "body": "baz2"}, + ] + + mocker.patch("duckduckgo_search.DDGS.text", return_value=mock_response) + + return DuckDuckGoWebSearchDriver() + + @pytest.fixture + def driver_with_error(self, mocker): + mocker.patch("duckduckgo_search.DDGS.text", side_effect=Exception("test_error")) + + return DuckDuckGoWebSearchDriver() + + def test_search_returns_results(self, driver): + results = driver.search("test") + assert isinstance(results, ListArtifact) + output = [json.loads(result.value) for result in results] + assert len(output) == 2 + assert output[0]["title"] == "foo" + assert output[0]["url"] == "bar" + assert output[0]["description"] == "baz" + + def test_search_raises_error(self, driver_with_error): + with pytest.raises(Exception, match="Error searching 'test' with DuckDuckGo: test_error"): + driver_with_error.search("test") diff --git a/tests/unit/drivers/web_search/test_google_web_search_driver.py b/tests/unit/drivers/web_search/test_google_web_search_driver.py new file mode 100644 index 000000000..9ecb92f46 --- /dev/null +++ b/tests/unit/drivers/web_search/test_google_web_search_driver.py @@ -0,0 +1,43 @@ +from pytest import fixture +import pytest +from griptape.drivers import GoogleWebSearchDriver +from griptape.artifacts import ErrorArtifact +import json +from pytest_mock import MockerFixture + + +class TestGoogleWebSearchDriver: + @fixture + def driver(self, mocker: MockerFixture): + mock_response = mocker.Mock() + mocker.patch.object( + mock_response, "json", return_value={"items": [{"title": "foo", "link": "bar", "snippet": "baz"}]} + ) + mock_response.status_code = 200 + + mocker.patch("requests.get", return_value=mock_response) + + return GoogleWebSearchDriver(api_key="test", search_id="test") + + @fixture + def driver_with_error(self, mocker: MockerFixture): + mock_response = mocker.Mock() + mock_response.status_code = 500 + mock_response.reason = "test_reason" + mocker.patch("requests.get", return_value=mock_response) + + return GoogleWebSearchDriver(api_key="test", search_id="test") + + def test_search_returns_results(self, driver): + results = driver.search("test") + output = [json.loads(result.value) for result in results] + assert len(output) == 1 + assert output[0]["title"] == "foo" + assert output[0]["url"] == "bar" + assert output[0]["description"] == "baz" + + def test_search_raises_error(self, driver_with_error): + with pytest.raises( + Exception, match="Google Search API returned an error with status code 500 and reason 'test_reason'" + ): + driver_with_error.search("test") diff --git a/tests/unit/engines/query/test_vector_query_engine.py b/tests/unit/engines/query/test_vector_query_engine.py deleted file mode 100644 index 17bde6888..000000000 --- a/tests/unit/engines/query/test_vector_query_engine.py +++ /dev/null @@ -1,58 +0,0 @@ -import pytest -from griptape.artifacts import TextArtifact, BaseArtifact -from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine -from griptape.loaders import TextLoader -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver -from tests.unit.chunkers.utils import gen_paragraph - -MAX_TOKENS = 50 - - -class TestVectorQueryEngine: - @pytest.fixture - def engine(self): - return VectorQueryEngine( - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - prompt_driver=MockPromptDriver(), - ) - - def test_query(self, engine): - artifacts = TextLoader(max_tokens=MAX_TOKENS).load( - gen_paragraph(MAX_TOKENS, engine.prompt_driver.tokenizer, ". ") - ) - - [engine.upsert_text_artifact(a) for a in artifacts] - - assert engine.query("foo").value.startswith("mock output") - - def test_upsert_text_artifact(self, engine): - engine.upsert_text_artifact(TextArtifact("foobar"), namespace="test") - - assert BaseArtifact.from_json(engine.vector_store_driver.load_entries()[0].meta["artifact"]).value == "foobar" - - def test_prompt_creation(self, engine): - system_message = engine.system_template_generator.render( - rulesets=["*RULESET*"], metadata="*META*", text_segments=["*TEXT SEGMENT 1*", "*TEXT SEGMENT 2*"] - ) - user_message = engine.user_template_generator.render(query="*QUESTION*") - - assert "*RULESET*" in system_message - - assert "*META*" in system_message - assert "*QUESTION*" in user_message - assert "*TEXT SEGMENT 1*" in system_message - assert "*TEXT SEGMENT 2*" in system_message - - def test_upsert_text_artifacts(self, engine): - engine.upsert_text_artifacts(artifacts=[TextArtifact("foobar1"), TextArtifact("foobar2")], namespace="test") - - assert BaseArtifact.from_json(engine.vector_store_driver.load_entries()[0].meta["artifact"]).value == "foobar1" - assert BaseArtifact.from_json(engine.vector_store_driver.load_entries()[1].meta["artifact"]).value == "foobar2" - - def test_load_artifacts(self, engine): - engine.upsert_text_artifacts(artifacts=[TextArtifact("foobar1"), TextArtifact("foobar2")], namespace="test") - - assert len(engine.load_artifacts("doesntexist")) == 0 - assert len(engine.load_artifacts("test")) == 2 diff --git a/tests/unit/engines/rag/__init__.py b/tests/unit/engines/rag/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/__init__.py b/tests/unit/engines/rag/modules/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/generation/__init__.py b/tests/unit/engines/rag/modules/generation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py new file mode 100644 index 000000000..e5ba50a5b --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py @@ -0,0 +1,33 @@ +import pytest +from griptape.artifacts import TextArtifact +from griptape.common import Reference +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import FootnotePromptResponseRagModule +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestFootnotePromptResponseRagModule: + @pytest.fixture + def module(self): + return FootnotePromptResponseRagModule(prompt_driver=MockPromptDriver()) + + def test_run(self, module): + assert module.run(RagContext(query="test")).output.value == "mock output" + + def test_prompt(self, module): + system_message = module.default_system_template_generator( + RagContext(query="test", before_query=["*RULESET*", "*META*"]), + artifacts=[ + TextArtifact("*TEXT SEGMENT 1*", reference=Reference(title="source 1")), + TextArtifact("*TEXT SEGMENT 2*", reference=Reference(title="source 2")), + TextArtifact("*TEXT SEGMENT 3*"), + ], + ) + + assert "*RULESET*" in system_message + assert "*META*" in system_message + assert "*TEXT SEGMENT 1*" in system_message + assert "*TEXT SEGMENT 2*" in system_message + assert "*TEXT SEGMENT 3*" in system_message + assert "source 1" in system_message + assert "source 2" in system_message diff --git a/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py new file mode 100644 index 000000000..9519c8017 --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_metadata_before_response_rag_module.py @@ -0,0 +1,21 @@ +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import MetadataBeforeResponseRagModule + + +class TestMetadataBeforeResponseRagModule: + def test_run(self): + module = MetadataBeforeResponseRagModule(name="foo") + + assert ( + "foo" in module.run(RagContext(module_configs={"foo": {"metadata": "foo"}}, query="test")).before_query[0] + ) + + def test_run_with_override(self): + module = MetadataBeforeResponseRagModule(name="foo", metadata="bar") + + assert ( + "bar" + in module.run( + RagContext(module_configs={"foo": {"query_params": {"metadata": "foo"}}}, query="test") + ).before_query[0] + ) diff --git a/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py new file mode 100644 index 000000000..f262d6d06 --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py @@ -0,0 +1,25 @@ +import pytest +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import PromptResponseRagModule +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestPromptResponseRagModule: + @pytest.fixture + def module(self): + return PromptResponseRagModule(prompt_driver=MockPromptDriver()) + + def test_run(self, module): + assert module.run(RagContext(query="test")).output.value == "mock output" + + def test_prompt(self, module): + system_message = module.default_system_template_generator( + RagContext(query="test", before_query=["*RULESET*", "*META*"], after_query=[]), + artifacts=[TextArtifact("*TEXT SEGMENT 1*"), TextArtifact("*TEXT SEGMENT 2*")], + ) + + assert "*RULESET*" in system_message + assert "*META*" in system_message + assert "*TEXT SEGMENT 1*" in system_message + assert "*TEXT SEGMENT 2*" in system_message diff --git a/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py new file mode 100644 index 000000000..2750257f4 --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py @@ -0,0 +1,10 @@ +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import RulesetsBeforeResponseRagModule +from griptape.rules import Ruleset, Rule + + +class TestRulesetsBeforeResponseRagModule: + def test_run(self): + module = RulesetsBeforeResponseRagModule(rulesets=[Ruleset(name="test ruleset", rules=[Rule("test rule")])]) + + assert "test rule" in module.run(RagContext(query="test")).before_query[0] diff --git a/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py new file mode 100644 index 000000000..6488d650e --- /dev/null +++ b/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py @@ -0,0 +1,15 @@ +import pytest +from griptape.artifacts import TextArtifact +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import TextChunksResponseRagModule + + +class TestTextChunksResponseRagModule: + @pytest.fixture + def module(self): + return TextChunksResponseRagModule() + + def test_run(self, module): + text_chunks = [TextArtifact("foo"), TextArtifact("bar")] + + assert module.run(RagContext(query="test", text_chunks=text_chunks)).output.value == text_chunks diff --git a/tests/unit/engines/rag/modules/query/__init__.py b/tests/unit/engines/rag/modules/query/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/retrieval/__init__.py b/tests/unit/engines/rag/modules/retrieval/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py new file mode 100644 index 000000000..fa3bfecb2 --- /dev/null +++ b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py @@ -0,0 +1,28 @@ +import pytest +from cohere import RerankResponseResultsItem, RerankResponseResultsItemDocument +from griptape.artifacts import TextArtifact +from griptape.drivers import CohereRerankDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import TextChunksRerankRagModule + + +class TestTextChunksRerankRagModule: + @pytest.fixture + def mock_client(self, mocker): + mock_client = mocker.patch("cohere.Client").return_value + mock_client.rerank.return_value.results = [ + RerankResponseResultsItem( + index=1, relevance_score=1.0, document=RerankResponseResultsItemDocument(text="foo") + ), + RerankResponseResultsItem( + index=2, relevance_score=0.5, document=RerankResponseResultsItemDocument(text="bar") + ), + ] + + return mock_client + + def test_run(self, mock_client): + module = TextChunksRerankRagModule(rerank_driver=CohereRerankDriver(api_key="api-key")) + result = module.run(RagContext(query="test", text_chunks=[TextArtifact("foo"), TextArtifact("bar")])) + + assert len(result) == 2 diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py new file mode 100644 index 000000000..7c69f674a --- /dev/null +++ b/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py @@ -0,0 +1,26 @@ +import pytest + +from griptape.drivers import LocalVectorStoreDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import TextLoaderRetrievalRagModule +from griptape.loaders import WebLoader +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver + +MAX_TOKENS = 50 + + +class TestTextLoaderRetrievalRagModule: + @pytest.fixture(autouse=True) + def mock_trafilatura_fetch_url(self, mocker): + mocker.patch("trafilatura.fetch_url", return_value="foobar") + + def test_run(self): + embedding_driver = MockEmbeddingDriver() + + module = TextLoaderRetrievalRagModule( + loader=WebLoader(max_tokens=MAX_TOKENS, embedding_driver=embedding_driver), + vector_store_driver=LocalVectorStoreDriver(embedding_driver=embedding_driver), + source="https://www.griptape.ai", + ) + + assert module.run(RagContext(query="foo"))[0].value == "foobar" diff --git a/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py new file mode 100644 index 000000000..9fecc3c0e --- /dev/null +++ b/tests/unit/engines/rag/modules/retrieval/test_vector_store_retrieval_rag_module.py @@ -0,0 +1,62 @@ +from griptape.artifacts import TextArtifact +from griptape.common import Reference +from griptape.drivers import LocalVectorStoreDriver +from griptape.engines.rag import RagContext +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver + + +class TestVectorStoreRetrievalRagModule: + def test_run_without_namespace(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + module = VectorStoreRetrievalRagModule(vector_store_driver=vector_store_driver) + + vector_store_driver.upsert_text_artifact( + TextArtifact("foobar1", reference=Reference(title="boo")), namespace="test" + ) + vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") + + result = module.run(RagContext(query="test")) + + assert len(result) == 2 + assert result[0].value == "foobar1" + assert result[1].value == "foobar2" + + def test_run_with_namespace(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + module = VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, query_params={"namespace": "test"} + ) + + vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") + vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") + + result = module.run(RagContext(query="test")) + + assert len(result) == 2 + assert result[0].value == "foobar1" + assert result[1].value == "foobar2" + + def test_run_with_namespace_overrides(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + module = VectorStoreRetrievalRagModule( + vector_store_driver=vector_store_driver, query_params={"namespace": "test"} + ) + + vector_store_driver.upsert_text_artifact(TextArtifact("foobar1"), namespace="test") + vector_store_driver.upsert_text_artifact(TextArtifact("foobar2"), namespace="test") + + result1 = module.run( + RagContext( + query="test", module_configs={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "empty"}}} + ) + ) + + result2 = module.run( + RagContext( + query="test", module_configs={"VectorStoreRetrievalRagModule": {"query_params": {"namespace": "test"}}} + ) + ) + + assert len(result1) == 0 + assert len(result2) == 2 diff --git a/tests/unit/engines/rag/modules/test_base_rag_nodule.py b/tests/unit/engines/rag/modules/test_base_rag_nodule.py new file mode 100644 index 000000000..be1fda861 --- /dev/null +++ b/tests/unit/engines/rag/modules/test_base_rag_nodule.py @@ -0,0 +1,27 @@ +from griptape.engines.rag import RagContext +from tests.mocks.mock_rag_module import MockRagModule + + +class TestBaseRagModule: + def test_generate_query_prompt_stack(self): + prompt_stack = MockRagModule().generate_query_prompt_stack("test system", "test query") + + assert len(prompt_stack.messages) == 2 + assert prompt_stack.messages[0].is_system() + assert prompt_stack.messages[1].is_user() + + def test_get_context_param(self): + module = MockRagModule(name="boo") + context = RagContext(query="test") + + context.module_configs["boo"] = {"foo": "bar"} + + assert module.get_context_param(context, "foo") == "bar" + + def test_set_context_param(self): + module = MockRagModule(name="boo") + context = RagContext(query="test") + + module.set_context_param(context, "foo", "bar") + + assert context.module_configs["boo"]["foo"] == "bar" diff --git a/tests/unit/engines/rag/test_rag_context.py b/tests/unit/engines/rag/test_rag_context.py new file mode 100644 index 000000000..7eba86683 --- /dev/null +++ b/tests/unit/engines/rag/test_rag_context.py @@ -0,0 +1,23 @@ +from griptape.artifacts import TextArtifact +from griptape.common import Reference +from griptape.engines.rag import RagContext + + +class TestRagContext: + def test_get_references(self): + reference1 = Reference(title="foo") + reference2 = Reference(title="bar") + context = RagContext( + query="foo", + text_chunks=[ + TextArtifact("foo", reference=reference1), + TextArtifact("foo", reference=reference1), + TextArtifact("foo"), + TextArtifact("foo", reference=reference2), + ], + ) + references = context.get_references() + + assert len(references) == 2 + assert references[0].id == reference1.id + assert references[1].id == reference2.id diff --git a/tests/unit/engines/rag/test_rag_engine.py b/tests/unit/engines/rag/test_rag_engine.py new file mode 100644 index 000000000..a39c0c2f1 --- /dev/null +++ b/tests/unit/engines/rag/test_rag_engine.py @@ -0,0 +1,50 @@ +import pytest +from griptape.drivers import LocalVectorStoreDriver +from griptape.engines.rag import RagEngine, RagContext +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestRagEngine: + @pytest.fixture + def engine(self): + return RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule( + vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + ) + ] + ), + response_stage=ResponseRagStage(response_module=PromptResponseRagModule(prompt_driver=MockPromptDriver())), + ) + + def test_module_name_uniqueness(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + + with pytest.raises(ValueError): + RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule(name="test", vector_store_driver=vector_store_driver), + VectorStoreRetrievalRagModule(name="test", vector_store_driver=vector_store_driver), + ] + ) + ) + + assert RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[ + VectorStoreRetrievalRagModule(name="test1", vector_store_driver=vector_store_driver), + VectorStoreRetrievalRagModule(name="test2", vector_store_driver=vector_store_driver), + ] + ) + ) + + def test_process_query(self, engine): + assert engine.process_query("test").output.value == "mock output" + + def test_process(self, engine): + assert engine.process(RagContext(query="test")).output.value == "mock output" diff --git a/tests/unit/engines/summary/test_prompt_summary_engine.py b/tests/unit/engines/summary/test_prompt_summary_engine.py index 59b36f48e..34c6e3563 100644 --- a/tests/unit/engines/summary/test_prompt_summary_engine.py +++ b/tests/unit/engines/summary/test_prompt_summary_engine.py @@ -1,7 +1,7 @@ import pytest from griptape.artifacts import TextArtifact, ListArtifact from griptape.engines import PromptSummaryEngine -from griptape.utils import PromptStack +from griptape.common import PromptStack from tests.mocks.mock_prompt_driver import MockPromptDriver import os @@ -28,7 +28,7 @@ def test_max_token_multiplier_invalid(self, engine): def test_chunked_summary(self, engine): def smaller_input(prompt_stack: PromptStack): - return prompt_stack.inputs[0].content[: (len(prompt_stack.inputs[0].content) // 2)] + return prompt_stack.messages[0].content[: (len(prompt_stack.messages[0].content) // 2)] engine = PromptSummaryEngine(prompt_driver=MockPromptDriver(mock_output="smaller_input")) diff --git a/tests/unit/events/test_base_event.py b/tests/unit/events/test_base_event.py index 7656b6b0d..595c90f1f 100644 --- a/tests/unit/events/test_base_event.py +++ b/tests/unit/events/test_base_event.py @@ -29,30 +29,48 @@ def test_to_dict(self): def test_start_prompt_event_from_dict(self): dict_value = { "type": "StartPromptEvent", - "timestamp": 123.0, - "token_count": 10, - "prompt_stack": {"inputs": [{"content": "foo", "role": "user"}, {"content": "bar", "role": "system"}]}, - "prompt": "foo bar", + "id": "917298d4bf894b0a824a8fdb26717a0c", + "timestamp": 123, "model": "foo bar", + "prompt_stack": { + "type": "PromptStack", + "messages": [ + { + "type": "Message", + "role": "user", + "content": [ + {"type": "TextMessageContent", "artifact": {"type": "TextArtifact", "value": "foo"}} + ], + "usage": {"type": "Usage", "input_tokens": None, "output_tokens": None}, + }, + { + "type": "Message", + "role": "system", + "content": [ + {"type": "TextMessageContent", "artifact": {"type": "TextArtifact", "value": "bar"}} + ], + "usage": {"type": "Usage", "input_tokens": None, "output_tokens": None}, + }, + ], + }, } event = BaseEvent.from_dict(dict_value) assert isinstance(event, StartPromptEvent) assert event.timestamp == 123 - assert event.token_count == 10 - assert event.prompt_stack.inputs[0].content == "foo" - assert event.prompt_stack.inputs[0].role == "user" - assert event.prompt_stack.inputs[1].content == "bar" - assert event.prompt_stack.inputs[1].role == "system" - assert event.prompt == "foo bar" + assert event.prompt_stack.messages[0].content[0].artifact.value == "foo" + assert event.prompt_stack.messages[0].role == "user" + assert event.prompt_stack.messages[1].content[0].artifact.value == "bar" + assert event.prompt_stack.messages[1].role == "system" assert event.model == "foo bar" def test_finish_prompt_event_from_dict(self): dict_value = { "type": "FinishPromptEvent", "timestamp": 123.0, - "token_count": 10, + "input_token_count": 10, + "output_token_count": 12, "result": "foo bar", "model": "foo bar", } @@ -61,7 +79,8 @@ def test_finish_prompt_event_from_dict(self): assert isinstance(event, FinishPromptEvent) assert event.timestamp == 123 - assert event.token_count == 10 + assert event.input_token_count == 10 + assert event.output_token_count == 12 assert event.result == "foo bar" assert event.model == "foo bar" diff --git a/tests/unit/events/test_finish_prompt_event.py b/tests/unit/events/test_finish_prompt_event.py index b788c67f9..7443fce0c 100644 --- a/tests/unit/events/test_finish_prompt_event.py +++ b/tests/unit/events/test_finish_prompt_event.py @@ -5,12 +5,13 @@ class TestFinishPromptEvent: @pytest.fixture def finish_prompt_event(self): - return FinishPromptEvent(token_count=123, result="foo bar", model="foo bar") + return FinishPromptEvent(input_token_count=321, output_token_count=123, result="foo bar", model="foo bar") def test_to_dict(self, finish_prompt_event): assert "timestamp" in finish_prompt_event.to_dict() - assert finish_prompt_event.to_dict()["token_count"] == 123 + assert finish_prompt_event.to_dict()["input_token_count"] == 321 + assert finish_prompt_event.to_dict()["output_token_count"] == 123 assert finish_prompt_event.to_dict()["result"] == "foo bar" assert finish_prompt_event.to_dict()["model"] == "foo bar" diff --git a/tests/unit/events/test_start_prompt_event.py b/tests/unit/events/test_start_prompt_event.py index a80f8cdfc..4ef08ec5c 100644 --- a/tests/unit/events/test_start_prompt_event.py +++ b/tests/unit/events/test_start_prompt_event.py @@ -1,24 +1,22 @@ import pytest from griptape.events import StartPromptEvent -from griptape.utils import PromptStack +from griptape.common import PromptStack class TestStartPromptEvent: @pytest.fixture def start_prompt_event(self): prompt_stack = PromptStack() - prompt_stack.add_user_input("foo") - prompt_stack.add_system_input("bar") - return StartPromptEvent(token_count=123, prompt_stack=prompt_stack, prompt="foo bar", model="foo bar") + prompt_stack.add_user_message("foo") + prompt_stack.add_system_message("bar") + return StartPromptEvent(prompt_stack=prompt_stack, model="foo bar") def test_to_dict(self, start_prompt_event): assert "timestamp" in start_prompt_event.to_dict() - assert start_prompt_event.to_dict()["token_count"] == 123 - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][0]["content"] == "foo" - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][0]["role"] == "user" - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][1]["content"] == "bar" - assert start_prompt_event.to_dict()["prompt_stack"]["inputs"][1]["role"] == "system" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][0]["content"][0]["artifact"]["value"] == "foo" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][0]["role"] == "user" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][1]["content"][0]["artifact"]["value"] == "bar" + assert start_prompt_event.to_dict()["prompt_stack"]["messages"][1]["role"] == "system" - assert start_prompt_event.to_dict()["prompt"] == "foo bar" assert start_prompt_event.to_dict()["model"] == "foo bar" diff --git a/tests/unit/memory/structure/test_conversation_memory.py b/tests/unit/memory/structure/test_conversation_memory.py index 298e5ac3f..613d4b1fe 100644 --- a/tests/unit/memory/structure/test_conversation_memory.py +++ b/tests/unit/memory/structure/test_conversation_memory.py @@ -1,17 +1,18 @@ import json from griptape.structures import Agent -from griptape.utils import PromptStack +from griptape.common import PromptStack from griptape.memory.structure import ConversationMemory, Run, BaseConversationMemory from griptape.structures import Pipeline from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tokenizer import MockTokenizer from griptape.tasks import PromptTask +from griptape.artifacts import TextArtifact class TestConversationMemory: def test_add_run(self): memory = ConversationMemory() - run = Run(input="test", output="test") + run = Run(input=TextArtifact("foo"), output=TextArtifact("bar")) memory.add_run(run) @@ -19,42 +20,42 @@ def test_add_run(self): def test_to_json(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert json.loads(memory.to_json())["type"] == "ConversationMemory" - assert json.loads(memory.to_json())["runs"][0]["input"] == "foo" + assert json.loads(memory.to_json())["runs"][0]["input"]["value"] == "foo" def test_to_dict(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert memory.to_dict()["type"] == "ConversationMemory" - assert memory.to_dict()["runs"][0]["input"] == "foo" + assert memory.to_dict()["runs"][0]["input"]["value"] == "foo" def test_to_prompt_stack(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) prompt_stack = memory.to_prompt_stack() - assert prompt_stack.inputs[0].content == "foo" - assert prompt_stack.inputs[1].content == "bar" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + assert prompt_stack.messages[1].content[0].artifact.value == "bar" def test_from_dict(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(BaseConversationMemory.from_dict(memory_dict), ConversationMemory) - assert BaseConversationMemory.from_dict(memory_dict).runs[0].input == "foo" + assert BaseConversationMemory.from_dict(memory_dict).runs[0].input.value == "foo" def test_from_json(self): memory = ConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(memory.from_dict(memory_dict), ConversationMemory) - assert memory.from_dict(memory_dict).runs[0].input == "foo" + assert memory.from_dict(memory_dict).runs[0].input.value == "foo" def test_buffering(self): memory = ConversationMemory(max_runs=2) @@ -70,28 +71,28 @@ def test_buffering(self): pipeline.run("run5") assert len(pipeline.conversation_memory.runs) == 2 - assert pipeline.conversation_memory.runs[0].input == "run4" - assert pipeline.conversation_memory.runs[1].input == "run5" + assert pipeline.conversation_memory.runs[0].input.value == "run4" + assert pipeline.conversation_memory.runs[1].input.value == "run5" def test_add_to_prompt_stack_autopruing_disabled(self): agent = Agent(prompt_driver=MockPromptDriver()) memory = ConversationMemory( autoprune=False, runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_user_message(TextArtifact("foo")) + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack) - assert len(prompt_stack.inputs) == 12 + assert len(prompt_stack.messages) == 12 def test_add_to_prompt_stack_autopruning_enabled(self): # All memory is pruned. @@ -99,42 +100,42 @@ def test_add_to_prompt_stack_autopruning_enabled(self): memory = ConversationMemory( autoprune=True, runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_system_message("fizz") + prompt_stack.add_user_message("foo") + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack) - assert len(prompt_stack.inputs) == 3 + assert len(prompt_stack.messages) == 3 # No memory is pruned. agent = Agent(prompt_driver=MockPromptDriver(tokenizer=MockTokenizer(model="foo", max_input_tokens=1000))) memory = ConversationMemory( autoprune=True, runs=[ - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_system_message("fizz") + prompt_stack.add_user_message("foo") + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack) - assert len(prompt_stack.inputs) == 13 + assert len(prompt_stack.messages) == 13 # One memory is pruned. # MockTokenizer's max_input_tokens set to one below the sum of memory + system prompt tokens @@ -144,25 +145,25 @@ def test_add_to_prompt_stack_autopruning_enabled(self): autoprune=True, runs=[ # All of these sum to 155 tokens with the MockTokenizer. - Run(input="foo1", output="bar1"), - Run(input="foo2", output="bar2"), - Run(input="foo3", output="bar3"), - Run(input="foo4", output="bar4"), - Run(input="foo5", output="bar5"), + Run(input=TextArtifact("foo1"), output=TextArtifact("bar1")), + Run(input=TextArtifact("foo2"), output=TextArtifact("bar2")), + Run(input=TextArtifact("foo3"), output=TextArtifact("bar3")), + Run(input=TextArtifact("foo4"), output=TextArtifact("bar4")), + Run(input=TextArtifact("foo5"), output=TextArtifact("bar5")), ], ) memory.structure = agent prompt_stack = PromptStack() # And then another 6 tokens from fizz for a total of 161 tokens. - prompt_stack.add_system_input("fizz") - prompt_stack.add_user_input("foo") - prompt_stack.add_assistant_input("bar") + prompt_stack.add_system_message("fizz") + prompt_stack.add_user_message("foo") + prompt_stack.add_assistant_message("bar") memory.add_to_prompt_stack(prompt_stack, 1) - # We expect one run (2 prompt stack inputs) to be pruned. - assert len(prompt_stack.inputs) == 11 - assert prompt_stack.inputs[0].content == "fizz" - assert prompt_stack.inputs[1].content == "foo2" - assert prompt_stack.inputs[2].content == "bar2" - assert prompt_stack.inputs[-2].content == "foo" - assert prompt_stack.inputs[-1].content == "bar" + # We expect one run (2 Prompt Stack inputs) to be pruned. + assert len(prompt_stack.messages) == 11 + assert prompt_stack.messages[0].content[0].artifact.value == "fizz" + assert prompt_stack.messages[1].content[0].artifact.value == "foo2" + assert prompt_stack.messages[2].content[0].artifact.value == "bar2" + assert prompt_stack.messages[-2].content[0].artifact.value == "foo" + assert prompt_stack.messages[-1].content[0].artifact.value == "bar" diff --git a/tests/unit/memory/structure/test_summary_conversation_memory.py b/tests/unit/memory/structure/test_summary_conversation_memory.py index 09792ff5d..e625ac6c6 100644 --- a/tests/unit/memory/structure/test_summary_conversation_memory.py +++ b/tests/unit/memory/structure/test_summary_conversation_memory.py @@ -1,9 +1,9 @@ import json -import pytest from griptape.memory.structure import Run, SummaryConversationMemory from griptape.structures import Pipeline +from griptape.artifacts import TextArtifact from griptape.tasks import PromptTask from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_structure_config import MockStructureConfig @@ -41,36 +41,36 @@ def test_after_run(self): def test_to_json(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert json.loads(memory.to_json())["type"] == "SummaryConversationMemory" - assert json.loads(memory.to_json())["runs"][0]["input"] == "foo" + assert json.loads(memory.to_json())["runs"][0]["input"]["value"] == "foo" def test_to_dict(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) assert memory.to_dict()["type"] == "SummaryConversationMemory" - assert memory.to_dict()["runs"][0]["input"] == "foo" + assert memory.to_dict()["runs"][0]["input"]["value"] == "foo" def test_to_prompt_stack(self): memory = SummaryConversationMemory(summary="foobar") - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) prompt_stack = memory.to_prompt_stack() - assert prompt_stack.inputs[0].content == "Summary of the conversation so far: foobar" - assert prompt_stack.inputs[1].content == "foo" - assert prompt_stack.inputs[2].content == "bar" + assert prompt_stack.messages[0].content[0].artifact.value == "Summary of the conversation so far: foobar" + assert prompt_stack.messages[1].content[0].artifact.value == "foo" + assert prompt_stack.messages[2].content[0].artifact.value == "bar" def test_from_dict(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(memory.from_dict(memory_dict), SummaryConversationMemory) - assert memory.from_dict(memory_dict).runs[0].input == "foo" - assert memory.from_dict(memory_dict).runs[0].output == "bar" + assert memory.from_dict(memory_dict).runs[0].input.value == "foo" + assert memory.from_dict(memory_dict).runs[0].output.value == "bar" assert memory.from_dict(memory_dict).offset == memory.offset assert memory.from_dict(memory_dict).summary == memory.summary assert memory.from_dict(memory_dict).summary_index == memory.summary_index @@ -78,11 +78,11 @@ def test_from_dict(self): def test_from_json(self): memory = SummaryConversationMemory() - memory.add_run(Run(input="foo", output="bar")) + memory.add_run(Run(input=TextArtifact("foo"), output=TextArtifact("bar"))) memory_dict = memory.to_dict() assert isinstance(memory.from_dict(memory_dict), SummaryConversationMemory) - assert memory.from_dict(memory_dict).runs[0].input == "foo" + assert memory.from_dict(memory_dict).runs[0].input.value == "foo" def test_config_prompt_driver(self): memory = SummaryConversationMemory() diff --git a/tests/unit/memory/tool/test_task_memory.py b/tests/unit/memory/tool/test_task_memory.py index ad7401fbb..fc1cf75c7 100644 --- a/tests/unit/memory/tool/test_task_memory.py +++ b/tests/unit/memory/tool/test_task_memory.py @@ -83,7 +83,7 @@ def test_load_artifacts_for_text_list_artifact(self, memory): memory.process_output( MockTool().test, ActionsSubtask(), - ListArtifact([TextArtifact("foo", name="test1"), TextArtifact("foo", name="test2")], name="test"), + ListArtifact([TextArtifact("foo1", name="test1"), TextArtifact("foo2", name="test2")], name="test"), ) assert len(memory.load_artifacts("test")) == 2 diff --git a/tests/unit/mixins/test_seriliazable_mixin.py b/tests/unit/mixins/test_seriliazable_mixin.py index d733d7858..1704000e3 100644 --- a/tests/unit/mixins/test_seriliazable_mixin.py +++ b/tests/unit/mixins/test_seriliazable_mixin.py @@ -23,16 +23,22 @@ def test_from_json(self): def test_str(self): assert str(MockSerializable()) == json.dumps( - {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None} + {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None, "nested": None} ) def test_to_json(self): assert MockSerializable().to_json() == json.dumps( - {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None} + {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None, "nested": None} ) def test_to_dict(self): - assert MockSerializable().to_dict() == {"type": "MockSerializable", "foo": "bar", "bar": None, "baz": None} + assert MockSerializable().to_dict() == { + "type": "MockSerializable", + "foo": "bar", + "bar": None, + "baz": None, + "nested": None, + } def test_import_class_rec(self): assert ( @@ -47,3 +53,8 @@ def test_import_class_rec(self): with pytest.raises(ValueError): MockSerializable._import_cls_rec("griptape.memory.task", "ConversationMemory") + + def test_nested_optional_serializable(self): + assert MockSerializable(nested=None).to_dict().get("nested") is None + + assert MockSerializable(nested=MockSerializable.NestedMockSerializable()).to_dict()["nested"]["foo"] == "bar" diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index e6c2a1f01..5dfcbc6d7 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -80,9 +80,11 @@ def test_embedding_driver(self): embedding_driver = MockEmbeddingDriver() agent = Agent(tools=[MockTool()], embedding_driver=embedding_driver) - artifact_storage = list(agent.task_memory.artifact_storages.values())[0] - assert isinstance(artifact_storage, TextArtifactStorage) - memory_embedding_driver = artifact_storage.query_engine.vector_store_driver.embedding_driver + storage = list(agent.task_memory.artifact_storages.values())[0] + assert isinstance(storage, TextArtifactStorage) + memory_embedding_driver = storage.rag_engine.retrieval_stage.retrieval_modules[ + 0 + ].vector_store_driver.embedding_driver assert memory_embedding_driver == embedding_driver @@ -164,15 +166,15 @@ def test_prompt_stack_without_memory(self): agent.add_task(task1) - assert len(task1.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 agent.run() - assert len(task1.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 agent.run() - assert len(task1.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 def test_prompt_stack_with_memory(self): agent = Agent(prompt_driver=MockPromptDriver(), conversation_memory=ConversationMemory()) @@ -181,15 +183,15 @@ def test_prompt_stack_with_memory(self): agent.add_task(task1) - assert len(task1.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 agent.run() - assert len(task1.prompt_stack.inputs) == 5 + assert len(task1.prompt_stack.messages) == 5 agent.run() - assert len(task1.prompt_stack.inputs) == 7 + assert len(task1.prompt_stack.messages) == 7 def test_run(self): task = PromptTask("test") @@ -236,8 +238,11 @@ def test_task_memory_defaults(self): storage = list(agent.task_memory.artifact_storages.values())[0] assert isinstance(storage, TextArtifactStorage) - assert storage.query_engine.prompt_driver == prompt_driver - assert storage.query_engine.vector_store_driver.embedding_driver == embedding_driver + assert storage.rag_engine.response_stage.response_module.prompt_driver == prompt_driver + assert ( + storage.rag_engine.retrieval_stage.retrieval_modules[0].vector_store_driver.embedding_driver + == embedding_driver + ) assert isinstance(storage.summary_engine, PromptSummaryEngine) assert storage.summary_engine.prompt_driver == prompt_driver assert storage.csv_extraction_engine.prompt_driver == prompt_driver @@ -262,3 +267,7 @@ def finished_tasks(self): agent.run("hello") assert len(agent.finished_tasks) == 1 + + def test_fail_fast(self): + with pytest.raises(ValueError): + Agent(prompt_driver=MockPromptDriver(), fail_fast=True) diff --git a/tests/unit/structures/test_pipeline.py b/tests/unit/structures/test_pipeline.py index 8c1cd8511..99c4141bf 100644 --- a/tests/unit/structures/test_pipeline.py +++ b/tests/unit/structures/test_pipeline.py @@ -1,10 +1,11 @@ import pytest +import time -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, ErrorArtifact from griptape.memory.task.storage import TextArtifactStorage from griptape.rules import Rule, Ruleset from griptape.tokenizers import OpenAiTokenizer -from griptape.tasks import PromptTask, BaseTask, ToolkitTask +from griptape.tasks import PromptTask, BaseTask, ToolkitTask, CodeExecutionTask from griptape.memory.structure import ConversationMemory from tests.mocks.mock_prompt_driver import MockPromptDriver from griptape.structures import Pipeline @@ -13,6 +14,21 @@ class TestPipeline: + @pytest.fixture + def waiting_task(self): + def fn(task): + time.sleep(2) + return TextArtifact("done") + + return CodeExecutionTask(run_fn=fn) + + @pytest.fixture + def error_artifact_task(self): + def fn(task): + return ErrorArtifact("error") + + return CodeExecutionTask(run_fn=fn) + def test_init(self): driver = MockPromptDriver() pipeline = Pipeline(prompt_driver=driver, rulesets=[Ruleset("TestRuleset", [Rule("test")])]) @@ -94,7 +110,9 @@ def test_embedding_driver(self): storage = list(pipeline.task_memory.artifact_storages.values())[0] assert isinstance(storage, TextArtifactStorage) - memory_embedding_driver = storage.query_engine.vector_store_driver.embedding_driver + memory_embedding_driver = storage.rag_engine.retrieval_stage.retrieval_modules[ + 0 + ].vector_store_driver.embedding_driver assert memory_embedding_driver == embedding_driver @@ -259,18 +277,18 @@ def test_prompt_stack_without_memory(self): pipeline.add_tasks(task1, task2) - assert len(task1.prompt_stack.inputs) == 2 - assert len(task2.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 + assert len(task2.prompt_stack.messages) == 2 pipeline.run() - assert len(task1.prompt_stack.inputs) == 3 - assert len(task2.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 + assert len(task2.prompt_stack.messages) == 3 pipeline.run() - assert len(task1.prompt_stack.inputs) == 3 - assert len(task2.prompt_stack.inputs) == 3 + assert len(task1.prompt_stack.messages) == 3 + assert len(task2.prompt_stack.messages) == 3 def test_prompt_stack_with_memory(self): pipeline = Pipeline(prompt_driver=MockPromptDriver()) @@ -280,18 +298,18 @@ def test_prompt_stack_with_memory(self): pipeline.add_tasks(task1, task2) - assert len(task1.prompt_stack.inputs) == 2 - assert len(task2.prompt_stack.inputs) == 2 + assert len(task1.prompt_stack.messages) == 2 + assert len(task2.prompt_stack.messages) == 2 pipeline.run() - assert len(task1.prompt_stack.inputs) == 5 - assert len(task2.prompt_stack.inputs) == 5 + assert len(task1.prompt_stack.messages) == 5 + assert len(task2.prompt_stack.messages) == 5 pipeline.run() - assert len(task1.prompt_stack.inputs) == 7 - assert len(task2.prompt_stack.inputs) == 7 + assert len(task1.prompt_stack.messages) == 7 + assert len(task2.prompt_stack.messages) == 7 def test_text_artifact_token_count(self): text = "foobar" @@ -355,3 +373,19 @@ def test_deprecation(self): with pytest.deprecated_call(): Pipeline(stream=True) + + def test_run_with_error_artifact(self, error_artifact_task, waiting_task): + end_task = PromptTask("end") + pipeline = Pipeline(prompt_driver=MockPromptDriver(), tasks=[waiting_task, error_artifact_task, end_task]) + pipeline.run() + + assert pipeline.output is None + + def test_run_with_error_artifact_no_fail_fast(self, error_artifact_task, waiting_task): + end_task = PromptTask("end") + pipeline = Pipeline( + prompt_driver=MockPromptDriver(), tasks=[waiting_task, error_artifact_task, end_task], fail_fast=False + ) + pipeline.run() + + assert pipeline.output is not None diff --git a/tests/unit/structures/test_workflow.py b/tests/unit/structures/test_workflow.py index bbcf5138e..bf55e852f 100644 --- a/tests/unit/structures/test_workflow.py +++ b/tests/unit/structures/test_workflow.py @@ -17,7 +17,7 @@ class TestWorkflow: @fixture def waiting_task(self): def fn(task): - time.sleep(10) + time.sleep(2) return TextArtifact("done") return CodeExecutionTask(run_fn=fn) @@ -108,7 +108,9 @@ def test_embedding_driver(self): storage = list(workflow.task_memory.artifact_storages.values())[0] assert isinstance(storage, TextArtifactStorage) - memory_embedding_driver = storage.query_engine.vector_store_driver.embedding_driver + memory_embedding_driver = storage.rag_engine.retrieval_stage.retrieval_modules[ + 0 + ].vector_store_driver.embedding_driver assert memory_embedding_driver == embedding_driver @@ -349,6 +351,44 @@ def test_run_topology_1_imperative_insert(self): self._validate_topology_1(workflow) + def test_run_topology_1_missing_parent(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + workflow = Workflow(prompt_driver=MockPromptDriver()) + + # task1 never added to workflow + workflow + task4 + with pytest.raises(ValueError): + workflow.insert_tasks(task1, [task2, task3], task4) + + def test_run_topology_1_id_equality(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + workflow = Workflow(prompt_driver=MockPromptDriver()) + + # task4 never added to workflow + workflow + task1 + workflow.insert_tasks(task1, [task2, task3], task4) + + with pytest.raises(ValueError): + workflow.run() + + def test_run_topology_1_object_equality(self): + task1 = PromptTask("test1", id="task1") + task2 = PromptTask("test2", id="task2") + task3 = PromptTask("test3", id="task3") + task4 = PromptTask("test4", id="task4") + workflow = Workflow(prompt_driver=MockPromptDriver()) + + workflow + task1 + workflow + task4 + with pytest.raises(ValueError): + workflow.insert_tasks(PromptTask("test1", id="task1"), [task2, task3], task4) + def test_run_topology_2_declarative_parents(self): workflow = Workflow( prompt_driver=MockPromptDriver(), @@ -643,7 +683,7 @@ def test_output_task(self): # task4 is the final task, but its defined at index 0 workflow = Workflow(prompt_driver=MockPromptDriver(), tasks=[task4, task1, task2, task3]) - # ouput_task topologically should be task4 + # output_task topologically should be task4 assert task4 == workflow.output_task def test_to_graph(self): @@ -726,6 +766,16 @@ def test_run_with_error_artifact(self, error_artifact_task, waiting_task): assert workflow.output is None + def test_run_with_error_artifact_no_fail_fast(self, error_artifact_task, waiting_task): + end_task = PromptTask("end") + end_task.add_parents([error_artifact_task, waiting_task]) + workflow = Workflow( + prompt_driver=MockPromptDriver(), tasks=[waiting_task, error_artifact_task, end_task], fail_fast=False + ) + workflow.run() + + assert workflow.output is not None + @staticmethod def _validate_topology_1(workflow): assert len(workflow.tasks) == 4 diff --git a/tests/unit/tasks/test_prompt_task.py b/tests/unit/tasks/test_prompt_task.py index 1dd45ab64..3a02309d3 100644 --- a/tests/unit/tasks/test_prompt_task.py +++ b/tests/unit/tasks/test_prompt_task.py @@ -1,4 +1,7 @@ import pytest +from griptape.artifacts.image_artifact import ImageArtifact +from griptape.artifacts.list_artifact import ListArtifact +from griptape.artifacts.text_artifact import TextArtifact from tests.mocks.mock_structure_config import MockStructureConfig from griptape.tasks import PromptTask from tests.mocks.mock_prompt_driver import MockPromptDriver @@ -32,3 +35,90 @@ def test_missing_prompt_driver(self): with pytest.raises(ValueError): task.prompt_driver + + def test_input(self): + # Str + task = PromptTask("test") + + assert task.input.value == "test" + + # List of strs + task = PromptTask(["test1", "test2"]) + + assert task.input.value[0].value == "test1" + assert task.input.value[1].value == "test2" + + # Tuple of strs + task = PromptTask(("test1", "test2")) + + assert task.input.value[0].value == "test1" + assert task.input.value[1].value == "test2" + + # Image artifact + task = PromptTask(ImageArtifact(b"image-data", format="png", width=100, height=100)) + + assert isinstance(task.input, ImageArtifact) + assert task.input.value == b"image-data" + assert task.input.format == "png" + assert task.input.width == 100 + assert task.input.height == 100 + + # List of str and image artifact + task = PromptTask(["foo", ImageArtifact(b"image-data", format="png", width=100, height=100)]) + + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 + + # List of str and nested image artifact + task = PromptTask(["foo", [ImageArtifact(b"image-data", format="png", width=100, height=100)]]) + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ListArtifact) + assert isinstance(task.input.value[1].value[0], ImageArtifact) + assert task.input.value[1].value[0].value == b"image-data" + assert task.input.value[1].value[0].format == "png" + assert task.input.value[1].value[0].width == 100 + + # Tuple of str and image artifact + task = PromptTask(("foo", ImageArtifact(b"image-data", format="png", width=100, height=100))) + + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 + + # Lambda returning list of str and image artifact + task = PromptTask( + ListArtifact([TextArtifact("foo"), ImageArtifact(b"image-data", format="png", width=100, height=100)]) + ) + + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 + + # Lambda returning list of str and image artifact + task = PromptTask( + lambda _: ListArtifact( + [TextArtifact("foo"), ImageArtifact(b"image-data", format="png", width=100, height=100)] + ) + ) + assert isinstance(task.input, ListArtifact) + assert task.input.value[0].value == "foo" + assert isinstance(task.input.value[1], ImageArtifact) + assert task.input.value[1].value == b"image-data" + assert task.input.value[1].format == "png" + assert task.input.value[1].width == 100 + + # default case + task = PromptTask({"default": "test"}) + + assert task.input.value == str({"default": "test"}) diff --git a/tests/unit/tasks/test_rag_task.py b/tests/unit/tasks/test_rag_task.py new file mode 100644 index 000000000..c9b82f208 --- /dev/null +++ b/tests/unit/tasks/test_rag_task.py @@ -0,0 +1,35 @@ +import pytest +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import PromptResponseRagModule +from griptape.engines.rag.stages import ResponseRagStage +from griptape.structures import Agent +from griptape.tasks import RagTask +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestRagTask: + @pytest.fixture + def task(self): + return RagTask( + input="test", + rag_engine=RagEngine( + response_stage=ResponseRagStage( + response_module=PromptResponseRagModule(prompt_driver=MockPromptDriver()) + ) + ), + ) + + def test_run(self, task): + agent = Agent() + + agent.add_task(task) + + assert task.run().to_text() == "mock output" + + def test_context_propagation(self, task): + task._input = "{{ test }}" + task.context = {"test": "test value"} + + Agent().add_task(task) + + assert task.input.to_text() == "test value" diff --git a/tests/unit/tasks/test_text_query_task.py b/tests/unit/tasks/test_text_query_task.py deleted file mode 100644 index 6ab0524be..000000000 --- a/tests/unit/tasks/test_text_query_task.py +++ /dev/null @@ -1,48 +0,0 @@ -from tests.mocks.mock_structure_config import MockStructureConfig -import pytest -from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine -from griptape.structures import Agent -from griptape.tasks import TextQueryTask -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver - - -class TestTextQueryTask: - @pytest.fixture - def task(self): - return TextQueryTask( - "test", - query_engine=VectorQueryEngine( - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - prompt_driver=MockPromptDriver(), - ), - namespace="test", - ) - - def test_run(self, task): - agent = Agent() - - agent.add_task(task) - - assert task.run().to_text() == "mock output" - - def test_context_propagation(self, task): - task._input = "{{ test }}" - task.context = {"test": "test value"} - - Agent().add_task(task) - - assert task.input.to_text() == "test value" - - def test_config_query_engine(self, task): - Agent(config=MockStructureConfig()).add_task(task) - - assert isinstance(task.query_engine, VectorQueryEngine) - assert isinstance(task.query_engine.prompt_driver, MockPromptDriver) - - def test_missing_summary_engine(self): - task = TextQueryTask("test") - - with pytest.raises(ValueError): - task.query_engine diff --git a/tests/unit/tasks/test_toolkit_task.py b/tests/unit/tasks/test_toolkit_task.py index f63b06d5b..cc05a5caf 100644 --- a/tests/unit/tasks/test_toolkit_task.py +++ b/tests/unit/tasks/test_toolkit_task.py @@ -1,13 +1,8 @@ -import pytest from griptape.artifacts import ErrorArtifact, TextArtifact -from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine from griptape.structures import Agent from griptape.tasks import ToolkitTask, ActionsSubtask, PromptTask -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tool.tool import MockTool -from tests.mocks.mock_value_prompt_driver import MockValuePromptDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.utils import defaults @@ -141,13 +136,6 @@ class TestToolkitSubtask: "$schema": "http://json-schema.org/draft-07/schema#", } - @pytest.fixture - def query_engine(self): - return VectorQueryEngine( - prompt_driver=MockPromptDriver(), - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - ) - def test_init(self): assert len(ToolkitTask("test", tools=[MockTool(name="Tool1"), MockTool(name="Tool2")]).tools) == 2 @@ -161,7 +149,7 @@ def test_run(self): output = """Answer: done""" task = ToolkitTask("test", tools=[MockTool(name="Tool1"), MockTool(name="Tool2")]) - agent = Agent(prompt_driver=MockValuePromptDriver(value=output)) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=output)) agent.add_task(task) @@ -175,7 +163,7 @@ def test_run_max_subtasks(self): output = """Actions: [{"name": "blah"}]""" task = ToolkitTask("test", tools=[MockTool(name="Tool1")], max_subtasks=3) - agent = Agent(prompt_driver=MockValuePromptDriver(value=output)) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=output)) agent.add_task(task) @@ -188,7 +176,7 @@ def test_run_invalid_react_prompt(self): output = """foo bar""" task = ToolkitTask("test", tools=[MockTool(name="Tool1")], max_subtasks=3) - agent = Agent(prompt_driver=MockValuePromptDriver(value=output)) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=output)) agent.add_task(task) @@ -279,7 +267,7 @@ def test_find_tool(self): assert task.find_tool(tool.name) == tool - def test_find_memory(self, query_engine): + def test_find_memory(self): m1 = defaults.text_task_memory("Memory1") m2 = defaults.text_task_memory("Memory2") @@ -291,7 +279,7 @@ def test_find_memory(self, query_engine): assert task.find_memory("Memory1") == m1 assert task.find_memory("Memory2") == m2 - def test_memory(self, query_engine): + def test_memory(self): tool1 = MockTool( name="Tool1", output_memory={"test": [defaults.text_task_memory("Memory1"), defaults.text_task_memory("Memory2")]}, diff --git a/tests/unit/tokenizers/test_google_tokenizer.py b/tests/unit/tokenizers/test_google_tokenizer.py index 955a0517f..34510cdac 100644 --- a/tests/unit/tokenizers/test_google_tokenizer.py +++ b/tests/unit/tokenizers/test_google_tokenizer.py @@ -1,6 +1,7 @@ import pytest from unittest.mock import Mock -from griptape.utils import PromptStack +from griptape.common import PromptStack +from griptape.common.prompt_stack.messages.message import Message from griptape.tokenizers import GoogleTokenizer @@ -19,7 +20,7 @@ def tokenizer(self, request): @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 5)], indirect=["tokenizer"]) def test_token_count(self, tokenizer, expected): assert tokenizer.count_tokens("foo bar huzzah") == expected - assert tokenizer.count_tokens(PromptStack(inputs=[PromptStack.Input(content="foo", role="user")])) == expected + assert tokenizer.count_tokens(PromptStack(messages=[Message(content="foo", role="user")])) == expected assert tokenizer.count_tokens(["foo", "bar", "huzzah"]) == expected @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 30715)], indirect=["tokenizer"]) diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index 082973bcb..210780729 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -166,10 +166,6 @@ def test_name(self): assert MockTool().name == "MockTool" assert MockTool(name="FooBar").name == "FooBar" - def test_class_name(self): - assert MockTool().class_name == "MockTool" - assert MockTool(name="FooBar").class_name == "MockTool" - def test_validate(self, tool): assert tool.validate() diff --git a/tests/unit/tools/test_rag_client.py b/tests/unit/tools/test_rag_client.py new file mode 100644 index 000000000..9c6497b02 --- /dev/null +++ b/tests/unit/tools/test_rag_client.py @@ -0,0 +1,13 @@ +from griptape.drivers import LocalVectorStoreDriver +from griptape.tools import RagClient +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.utils.defaults import rag_engine + + +class TestRagClient: + def test_search(self): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool = RagClient(description="Test", rag_engine=rag_engine(MockPromptDriver(), vector_store_driver)) + + assert tool.search({"values": {"query": "test"}}).value == "mock output" diff --git a/tests/unit/tools/test_vector_store_client.py b/tests/unit/tools/test_vector_store_client.py index ef54ed024..45018b847 100644 --- a/tests/unit/tools/test_vector_store_client.py +++ b/tests/unit/tools/test_vector_store_client.py @@ -1,26 +1,42 @@ import pytest -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, ListArtifact from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine from griptape.tools import VectorStoreClient from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from tests.mocks.mock_prompt_driver import MockPromptDriver class TestVectorStoreClient: @pytest.fixture(autouse=True) - def mock_try_runt(self, mocker): - mocker.patch("griptape.drivers.OpenAiChatPromptDriver.try_run", return_value=TextArtifact("foobar")) - + def mock_try_run(self, mocker): mocker.patch("griptape.drivers.OpenAiEmbeddingDriver.try_embed_chunk", return_value=[0, 1]) def test_search(self): - tool = VectorStoreClient( + driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool = VectorStoreClient(description="Test", vector_store_driver=driver) + + driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) + + assert set([a.value for a in tool.search({"values": {"query": "test"}})]) == {"foo", "bar"} + + def test_search_with_namespace(self): + driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool1 = VectorStoreClient(description="Test", vector_store_driver=driver, query_params={"namespace": "test"}) + tool2 = VectorStoreClient(description="Test", vector_store_driver=driver, query_params={"namespace": "test2"}) + + driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) + + assert len(tool1.search({"values": {"query": "test"}})) == 2 + assert len(tool2.search({"values": {"query": "test"}})) == 0 + + def test_custom_process_query_output_fn(self): + driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + tool1 = VectorStoreClient( description="Test", - query_engine=VectorQueryEngine( - prompt_driver=MockPromptDriver(mock_output="foobar"), - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - ), + vector_store_driver=driver, + process_query_output_fn=lambda es: ListArtifact([e.vector for e in es]), + query_params={"include_vectors": True}, ) - assert tool.search({"values": {"query": "test"}}).value == "foobar" + driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) + + assert tool1.search({"values": {"query": "test"}}).value == [[0, 1], [0, 1]] diff --git a/tests/unit/tools/test_web_search.py b/tests/unit/tools/test_web_search.py index c9a79b452..0abc880c8 100644 --- a/tests/unit/tools/test_web_search.py +++ b/tests/unit/tools/test_web_search.py @@ -1,34 +1,32 @@ -from griptape.artifacts import BaseArtifact, ErrorArtifact +import pytest +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import WebSearch -from pytest import fixture -import json class TestWebSearch: - @fixture + @pytest.fixture def websearch_tool(self, mocker): - mock_response = mocker.Mock() - mock_response.status_code = 200 - mock_response.json.return_value = {"items": [{"title": "foo", "link": "bar", "snippet": "baz"}]} - mocker.patch("requests.get", return_value=mock_response) + mock_response = TextArtifact("test_response") + driver = mocker.Mock() + mocker.patch.object(driver, "search", return_value=mock_response) - return WebSearch(google_api_key="foo", google_api_search_id="bar") + return WebSearch(web_search_driver=driver) - @fixture + @pytest.fixture def websearch_tool_with_error(self, mocker): - mock_response = mocker.Mock() - mock_response.status_code = 500 - mocker.patch("requests.get", return_value=mock_response) + mock_response = Exception("test_error") + driver = mocker.Mock() + mocker.patch.object(driver, "search", side_effect=mock_response) - return WebSearch(google_api_key="foo", google_api_search_id="bar") + return WebSearch(web_search_driver=driver) def test_search(self, websearch_tool): assert isinstance(websearch_tool.search({"values": {"query": "foo bar"}}), BaseArtifact) - assert json.loads(websearch_tool.search({"values": {"query": "foo bar"}}).value[0].value) == { - "title": "foo", - "url": "bar", - "description": "baz", - } + assert websearch_tool.search({"values": {"query": "foo bar"}}).value == "test_response" def test_search_with_error(self, websearch_tool_with_error): assert isinstance(websearch_tool_with_error.search({"values": {"query": "foo bar"}}), ErrorArtifact) + assert ( + websearch_tool_with_error.search({"values": {"query": "foo bar"}}).value + == "Error searching 'foo bar' with Mock: test_error" + ) diff --git a/tests/unit/utils/test_base_tokenizer.py b/tests/unit/utils/test_base_tokenizer.py new file mode 100644 index 000000000..eed15b9b2 --- /dev/null +++ b/tests/unit/utils/test_base_tokenizer.py @@ -0,0 +1,13 @@ +import logging +from tests.mocks.mock_tokenizer import MockTokenizer + + +class TestBaseTokenizer: + def test_default_tokens(self, caplog): + with caplog.at_level(logging.WARNING): + tokenizer = MockTokenizer(model="gpt2") + + assert tokenizer.max_input_tokens == 4096 + assert tokenizer.max_output_tokens == 1000 + + assert "gpt2 not found" in caplog.text diff --git a/tests/unit/utils/test_dict_utils.py b/tests/unit/utils/test_dict_utils.py index ba6d5470d..958e0295b 100644 --- a/tests/unit/utils/test_dict_utils.py +++ b/tests/unit/utils/test_dict_utils.py @@ -10,7 +10,7 @@ def test_remove_null_values_in_dict_recursively(self): assert remove_null_values_in_dict_recursively(dict_with_nones) == dict_without_nones - def test_merges_dicts(self): + def test_dict_merge_merges_dicts(self): a = {"a": 1, "b": {"b1": 2, "b2": 3}} b = {"a": 1, "b": {"b1": 4}} @@ -18,7 +18,22 @@ def test_merges_dicts(self): assert dict_merge(a, b)["b"]["b2"] == 3 assert dict_merge(a, b)["b"]["b1"] == 4 - def test_inserts_new_keys(self): + def test_dict_merge_works_with_optionals(self): + a = {"a": 1, "b": {"b1": 2, "b2": 3}} + b = None + + assert dict_merge(a, b)["a"] == 1 + assert dict_merge(a, b)["b"]["b2"] == 3 + assert dict_merge(a, b)["b"]["b1"] == 2 + + a = None + b = {"a": 1, "b": {"b1": 2, "b2": 3}} + + assert dict_merge(a, b)["a"] == 1 + assert dict_merge(a, b)["b"]["b2"] == 3 + assert dict_merge(a, b)["b"]["b1"] == 2 + + def test_dict_merge_inserts_new_keys(self): a = {"a": 1, "b": {"b1": 2, "b2": 3}} b = {"a": 1, "b": {"b1": 4, "b3": 5}, "c": 6} @@ -28,7 +43,7 @@ def test_inserts_new_keys(self): assert dict_merge(a, b)["b"]["b3"] == 5 assert dict_merge(a, b)["c"] == 6 - def test_does_not_insert_new_keys(self): + def test_dict_merge_does_not_insert_new_keys(self): a = {"a": 1, "b": {"b1": 2, "b2": 3}} b = {"a": 1, "b": {"b1": 4, "b3": 5}, "c": 6} diff --git a/tests/unit/utils/test_futures.py b/tests/unit/utils/test_futures.py index d50416f58..5e30148a9 100644 --- a/tests/unit/utils/test_futures.py +++ b/tests/unit/utils/test_futures.py @@ -12,5 +12,14 @@ def test_execute_futures_dict(self): assert result["foo"] == "foo-bar" assert result["baz"] == "baz-bar" + def test_execute_futures_list(self): + with futures.ThreadPoolExecutor() as executor: + result = utils.execute_futures_list( + [executor.submit(self.foobar, "foo"), executor.submit(self.foobar, "baz")] + ) + + assert result[0] == "foo-bar" + assert result[1] == "baz-bar" + def foobar(self, foo): return f"{foo}-bar" diff --git a/tests/unit/utils/test_message_stack.py b/tests/unit/utils/test_message_stack.py new file mode 100644 index 000000000..908388a33 --- /dev/null +++ b/tests/unit/utils/test_message_stack.py @@ -0,0 +1,55 @@ +import pytest + +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact +from griptape.common import ImageMessageContent, PromptStack, TextMessageContent + + +class TestPromptStack: + @pytest.fixture + def prompt_stack(self): + return PromptStack() + + def test_init(self): + assert PromptStack() + + def test_add_message(self, prompt_stack): + prompt_stack.add_message("foo", "role") + prompt_stack.add_message(TextArtifact("foo"), "role") + prompt_stack.add_message(ImageArtifact(b"foo", format="png", width=100, height=100), "role") + prompt_stack.add_message(ListArtifact([TextArtifact("foo"), TextArtifact("bar")]), "role") + + assert prompt_stack.messages[0].role == "role" + assert isinstance(prompt_stack.messages[0].content[0], TextMessageContent) + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + assert prompt_stack.messages[1].role == "role" + assert isinstance(prompt_stack.messages[1].content[0], TextMessageContent) + assert prompt_stack.messages[1].content[0].artifact.value == "foo" + + assert prompt_stack.messages[2].role == "role" + assert isinstance(prompt_stack.messages[2].content[0], ImageMessageContent) + assert prompt_stack.messages[2].content[0].artifact.value == b"foo" + + assert prompt_stack.messages[3].role == "role" + assert isinstance(prompt_stack.messages[3].content[0], TextMessageContent) + assert prompt_stack.messages[3].content[0].artifact.value == "foo" + assert isinstance(prompt_stack.messages[3].content[1], TextMessageContent) + assert prompt_stack.messages[3].content[1].artifact.value == "bar" + + def test_add_system_message(self, prompt_stack): + prompt_stack.add_system_message("foo") + + assert prompt_stack.messages[0].role == "system" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + def test_add_user_message(self, prompt_stack): + prompt_stack.add_user_message("foo") + + assert prompt_stack.messages[0].role == "user" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + def test_add_assistant_message(self, prompt_stack): + prompt_stack.add_assistant_message("foo") + + assert prompt_stack.messages[0].role == "assistant" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" diff --git a/tests/unit/utils/test_prompt_stack.py b/tests/unit/utils/test_prompt_stack.py deleted file mode 100644 index 80010abec..000000000 --- a/tests/unit/utils/test_prompt_stack.py +++ /dev/null @@ -1,41 +0,0 @@ -import pytest -from griptape.utils import PromptStack - - -class TestPromptStack: - @pytest.fixture - def prompt_stack(self): - return PromptStack() - - def test_init(self): - assert PromptStack() - - def test_add_input(self, prompt_stack): - prompt_stack.add_input("foo", "role") - - assert prompt_stack.inputs[0].role == "role" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_generic_input(self, prompt_stack): - prompt_stack.add_generic_input("foo") - - assert prompt_stack.inputs[0].role == "generic" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_system_input(self, prompt_stack): - prompt_stack.add_system_input("foo") - - assert prompt_stack.inputs[0].role == "system" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_user_input(self, prompt_stack): - prompt_stack.add_user_input("foo") - - assert prompt_stack.inputs[0].role == "user" - assert prompt_stack.inputs[0].content == "foo" - - def test_add_assistant_input(self, prompt_stack): - prompt_stack.add_assistant_input("foo") - - assert prompt_stack.inputs[0].role == "assistant" - assert prompt_stack.inputs[0].content == "foo" diff --git a/tests/unit/utils/test_structure_visualizer.py b/tests/unit/utils/test_structure_visualizer.py index d7177bf30..e16275a5c 100644 --- a/tests/unit/utils/test_structure_visualizer.py +++ b/tests/unit/utils/test_structure_visualizer.py @@ -11,7 +11,7 @@ def test_agent(self): visualizer = StructureVisualizer(agent) result = visualizer.to_url() - assert result == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMTs=" + assert result == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgljYzVkYWYyNih0YXNrMSk7" def test_pipeline(self): pipeline = Pipeline( @@ -29,7 +29,7 @@ def test_pipeline(self): assert ( result - == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMS0tPiB0YXNrMjsKCXRhc2syLS0+IHRhc2szOwoJdGFzazMtLT4gdGFzazQ7Cgl0YXNrNDs=" + == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgljYzVkYWYyNih0YXNrMSktLT4gYWE1ZGU4N2UodGFzazIpOwoJYWE1ZGU4N2UodGFzazIpLS0+IDUxZmViYjIxKHRhc2szKTsKCTUxZmViYjIxKHRhc2szKS0tPiBhN2JlMzY4Yih0YXNrNCk7CglhN2JlMzY4Yih0YXNrNCk7" ) def test_workflow(self): @@ -48,5 +48,5 @@ def test_workflow(self): assert ( result - == "https://mermaid.ink/svg/Z3JhcGggVEQ7Cgl0YXNrMS0tPiB0YXNrMiAmIHRhc2szOwoJdGFzazItLT4gdGFzazQ7Cgl0YXNrMy0tPiB0YXNrNDsKCXRhc2s0Ow==" + == "https://mermaid.ink/svg/Z3JhcGggVEQ7CgljYzVkYWYyNih0YXNrMSktLT4gYWE1ZGU4N2UodGFzazIpICYgNTFmZWJiMjEodGFzazMpOwoJYWE1ZGU4N2UodGFzazIpLS0+IGE3YmUzNjhiKHRhc2s0KTsKCTUxZmViYjIxKHRhc2szKS0tPiBhN2JlMzY4Yih0YXNrNCk7CglhN2JlMzY4Yih0YXNrNCk7" ) diff --git a/tests/utils/code_blocks.py b/tests/utils/code_blocks.py index 09a4695ba..9cfebb987 100644 --- a/tests/utils/code_blocks.py +++ b/tests/utils/code_blocks.py @@ -1,3 +1,4 @@ +import logging import pathlib import textwrap @@ -13,7 +14,7 @@ def check_py_string(source: str) -> None: try: exec(source, {"__MODULE__": "__main__"}) except Exception: - print(source) + logging.info(source) raise diff --git a/tests/utils/defaults.py b/tests/utils/defaults.py index 801eed7de..5a9f6f958 100644 --- a/tests/utils/defaults.py +++ b/tests/utils/defaults.py @@ -1,6 +1,9 @@ from griptape.artifacts import TextArtifact, BlobArtifact from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import VectorQueryEngine, PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine +from griptape.engines import PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine +from griptape.engines.rag import RagEngine +from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule +from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage from griptape.memory import TaskMemory from griptape.memory.task.storage import TextArtifactStorage, BlobArtifactStorage from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -8,11 +11,12 @@ def text_tool_artifact_storage(): + vector_store_driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) + return TextArtifactStorage( - query_engine=VectorQueryEngine( - vector_store_driver=LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()), - prompt_driver=MockPromptDriver(), - ), + rag_engine=rag_engine(MockPromptDriver(), vector_store_driver), + vector_store_driver=vector_store_driver, + retrieval_rag_module_name="VectorStoreRetrievalRagModule", summary_engine=PromptSummaryEngine(prompt_driver=MockPromptDriver()), csv_extraction_engine=CsvExtractionEngine(prompt_driver=MockPromptDriver()), json_extraction_engine=JsonExtractionEngine(prompt_driver=MockPromptDriver()), @@ -23,3 +27,12 @@ def text_task_memory(name): return TaskMemory( name=name, artifact_storages={TextArtifact: text_tool_artifact_storage(), BlobArtifact: BlobArtifactStorage()} ) + + +def rag_engine(prompt_driver, vector_store_driver): + return RagEngine( + retrieval_stage=RetrievalRagStage( + retrieval_modules=[VectorStoreRetrievalRagModule(vector_store_driver=vector_store_driver)] + ), + response_stage=ResponseRagStage(response_module=PromptResponseRagModule(prompt_driver=prompt_driver)), + ) diff --git a/tests/utils/test_reference_utils.py b/tests/utils/test_reference_utils.py new file mode 100644 index 000000000..c3491f5d0 --- /dev/null +++ b/tests/utils/test_reference_utils.py @@ -0,0 +1,22 @@ +from griptape.artifacts import TextArtifact +from griptape.common import Reference +from griptape.engines.rag.modules import PromptResponseRagModule +from tests.mocks.mock_prompt_driver import MockPromptDriver + + +class TestReferenceUtils: + def test_references_from_artifacts(self): + module = PromptResponseRagModule(prompt_driver=MockPromptDriver()) + reference1 = Reference(title="foo") + reference2 = Reference(title="bar") + artifacts = [ + TextArtifact("foo", reference=reference1), + TextArtifact("foo", reference=reference1), + TextArtifact("foo"), + TextArtifact("foo", reference=reference2), + ] + references = module.references_from_artifacts(artifacts) + + assert len(references) == 2 + assert references[0].id == reference1.id + assert references[1].id == reference2.id From 54bbe2b8892802c7134ea999d7b39a8afcf5a1cd Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 9 Jul 2024 12:24:41 -0700 Subject: [PATCH 46/87] Version bump v0.28.0 (#949) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index c1b6b934c..ffcba09af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "griptape" -version = "0.27.2" +version = "0.28.0" description = "Modular Python framework for LLM workflows, tools, memory, and data." authors = ["Griptape "] license = "Apache 2.0" From 4ef133f3be969b07fec25869874ca2f0e613b895 Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Wed, 10 Jul 2024 08:13:11 -0700 Subject: [PATCH 47/87] Remove duplicate info from changelog (#952) --- CHANGELOG.md | 72 ---------------------------------------------------- 1 file changed, 72 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a57ca94b1..5a84861a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,82 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added -- `RagEngine` is an abstraction for implementing modular RAG pipelines. - - `RagContext` is a container object for passing around RAG context. - - RAG stages: - - `QueryRagStage` for parsing and expanding queries. - - `RetrievalRagStage` for retrieving content. - - `ResponseRagStage` for augmenting and generating outputs. - - RAG modules: - - Retrieval: - - `VectorStoreRetrievalRagModule` for retrieving text chunks from vector stores. - - `TextLoaderRetrievalRagModule` for retrieving data with text loaders in real time. - - `TextChunksRerankRagModule` for re-ranking retrieved results. - - Response: - - `MetadataBeforeResponseRagModule` for appending metadata. - - `RulesetsBeforeResponseRagModule` for appending rulesets. - - `PromptResponseRagModule` for generating responses based on retrieved text chunks. - - `TextChunksResponseRagModule` for responding with retrieved text chunks. - - `FootnotePromptResponseRagModule` for responding with automatic footnotes from text chunk references. -- `RagClient` tool for exposing `RagEngines` to LLM agents. -- `RagTask` task for including `RagEngines` in any structure. -- Rerank drivers: - - `CohereRerankDriver` for using the Cohere rerank API. -- `utils.execute_futures_list()` for executing a list of futures. -- `LocalVectorStoreDriver.persist_file` for persisting vectors and chunks in a text file. -- `Entry.to_artifact()` for easy vector store entry conversions into Griptape artifacts. -- `BaseVectorStoreDriver.does_entry_exist()` to check if an entry exists in the vector store. -- `GoogleWebSearchDriver` to web search with the Google Customsearch API. -- `DuckDuckGoWebSearchDriver` to web search with the DuckDuckGo search SDK. -- `ProxyWebScraperDriver` to web scrape using proxies. -- Parameter `session` on `AmazonBedrockStructureConfig`. -- Parameter `meta` on `TextArtifact`. -- `VectorStoreClient` improvements: - - `VectorStoreClient.query_params` dict for custom query params. - - `VectorStoreClient.process_query_output_fn` for custom query output processing logic. -- Parameter `fail_fast` to `Structure`. -- `BooleanArtifact` for handling boolean values. -- `typos` to dev dependencies to catch typos in code/docs. -- `Message` for storing messages in a `PromptStack`. Messages consist of a role, content, and usage. -- `DeltaMessage` for storing partial messages in a `PromptStack`. Multiple `DeltaMessage` can be combined to form a `Message`. -- `TextMessageContent` for storing textual content in a `Message`. -- `ImageMessageContent` for storing image content in a `Message`. -- Support for adding `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s to `PromptStack`. -- Support for image inputs to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AmazonBedrockPromptDriver`, `AnthropicPromptDriver`, and `GooglePromptDriver`. -- Input/output token usage metrics to all Prompt Drivers. -- `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. -- Support for storing Artifacts as inputs/outputs in Conversation Memory Runs. -- `Agent.input` for passing Artifacts as input. -- Support for `PromptTask`s to take `TextArtifact`s, `ImageArtifact`s, and `ListArtifact`s as input. -- Parameters `sort_key` and `sort_key_value` on `AmazonDynamoDbConversationMemoryDriver` for tables with sort keys. -- `Reference` for supporting artifact citations in loaders and RAG engine modules. ### Changed -- **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. -- **BREAKING**: Renamed `PromptStack.inputs` to `PromptStack.messages`. -- **BREAKING**: Moved `PromptStack.USER_ROLE`, `PromptStack.ASSISTANT_ROLE`, and `PromptStack.SYSTEM_ROLE` to `Message`. -- **BREAKING**: Updated return type of `PromptDriver.try_run` from `TextArtifact` to `Message`. -- **BREAKING**: Updated return type of `PromptDriver.try_stream` from `Iterator[TextArtifact]` to `Iterator[DeltaMessage]`. -- **BREAKING**: Removed `BasePromptEvent.token_count` in favor of `FinishPromptEvent.input_token_count` and `FinishPromptEvent.output_token_count`. -- **BREAKING**: Removed `StartPromptEvent.prompt`. Use `StartPromptEvent.prompt_stack` instead. -- **BREAKING**: Removed `Agent.input_template` in favor of `Agent.input`. -- **BREAKING**: `BasePromptDriver.run` now returns a `Message` instead of a `TextArtifact`. For compatibility, `Message.value` contains the Message's Artifact value -- **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact()` and `BaseVectorStoreDriver.upsert_text()` use artifact/string values to generate `vector_id` if it wasn't implicitly passed. This change ensures that we don't generate embeddings for the same content every time. -- **BREAKING**: Removed `VectorQueryEngine` in favor of `RagEngine`. -- **BREAKING**: Removed `TextQueryTask` in favor of `RagTask`. -- **BREAKING**: `TextArtifactStorage` now requires `vector_store_driver` and `rag_engine` in place of `vector_query_engine`. -- **BREAKING**: Moved `load_artifacts()` from `BaseQueryEngine` to `BaseVectorStoreDriver`. -- **BREAKING**: Merged `BaseVectorStoreDriver.QueryResult` into `BaseVectorStoreDriver.Entry`. -- **BREAKING**: Replaced `query_engine` with `vector_store_driver` in `VectorStoreClient`. -- **BREAKING**: removed parameters `google_api_lang`, `google_api_key`, `google_api_search_id`, `google_api_country` on `WebSearch` in favor of `web_search_driver`. -- **BREAKING**: removed `VectorStoreClient.top_n` and `VectorStoreClient.namespace` in favor of `VectorStoreClient.query_params`. -- **BREAKING**: All `futures_executor` fields renamed to `futures_executor_fn` and now accept callables instead of futures; wrapped all future `submit` calls with the `with` block to address future executor shutdown issues. -- `GriptapeCloudKnowledgeBaseClient` migrated to `/search` api. -- Default Prompt Driver model in `GoogleStructureConfig` to `gemini-1.5-pro`. ### Fixed -- `CoherePromptDriver` to properly handle empty history. -- `StructureVisualizer.to_url()` by wrapping task IDs in single quotes. ## [0.28.0] - 2024-07-09 ### Added From c20617a5c2763b372aa25d4e18698a56c2e98646 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 10 Jul 2024 11:20:17 -0700 Subject: [PATCH 48/87] Add Ollama Embedding Driver (#953) --- CHANGELOG.md | 1 + .../drivers/embedding-drivers.md | 20 +++++++++++++ griptape/drivers/__init__.py | 2 ++ .../embedding/ollama_embedding_driver.py | 28 +++++++++++++++++++ poetry.lock | 14 ++++++++-- pyproject.toml | 1 + .../embedding/test_ollama_embedding_driver.py | 18 ++++++++++++ 7 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 griptape/drivers/embedding/ollama_embedding_driver.py create mode 100644 tests/unit/drivers/embedding/test_ollama_embedding_driver.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a84861a3..aa3b06a95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added +- `OllamaEmbeddingDriver` for generating embeddings with Ollama. ### Changed diff --git a/docs/griptape-framework/drivers/embedding-drivers.md b/docs/griptape-framework/drivers/embedding-drivers.md index 3f0135ac3..a607b0950 100644 --- a/docs/griptape-framework/drivers/embedding-drivers.md +++ b/docs/griptape-framework/drivers/embedding-drivers.md @@ -97,8 +97,28 @@ embeddings = driver.embed_string("Hello world!") # display the first 3 embeddings print(embeddings[:3]) +``` + +### Ollama + +!!! info + This driver requires the `drivers-embedding-ollama` [extra](../index.md#extras). + +The [OllamaEmbeddingDriver](../../reference/griptape/drivers/embedding/ollama_embedding_driver.md) uses the [Ollama Embeddings API](https://ollama.com/blog/embedding-models). + +```python title="PYTEST_IGNORE" +from griptape.drivers import OllamaEmbeddingDriver + +driver = OllamaEmbeddingDriver( + model="all-minilm", +) +results = driver.embed_string("Hello world!") + +# display the first 3 embeddings +print(results[:3]) ``` + ### Amazon SageMaker Jumpstart The [AmazonSageMakerJumpstartEmbeddingDriver](../../reference/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.md) uses the [Amazon SageMaker Endpoints](https://docs.aws.amazon.com/sagemaker/latest/dg/realtime-endpoints.html) to generate embeddings on AWS. diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index fa2934a38..4e0fe6672 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -27,6 +27,7 @@ from .embedding.google_embedding_driver import GoogleEmbeddingDriver from .embedding.dummy_embedding_driver import DummyEmbeddingDriver from .embedding.cohere_embedding_driver import CohereEmbeddingDriver +from .embedding.ollama_embedding_driver import OllamaEmbeddingDriver from .vector.base_vector_store_driver import BaseVectorStoreDriver from .vector.local_vector_store_driver import LocalVectorStoreDriver @@ -135,6 +136,7 @@ "GoogleEmbeddingDriver", "DummyEmbeddingDriver", "CohereEmbeddingDriver", + "OllamaEmbeddingDriver", "BaseVectorStoreDriver", "LocalVectorStoreDriver", "PineconeVectorStoreDriver", diff --git a/griptape/drivers/embedding/ollama_embedding_driver.py b/griptape/drivers/embedding/ollama_embedding_driver.py new file mode 100644 index 000000000..d081321c1 --- /dev/null +++ b/griptape/drivers/embedding/ollama_embedding_driver.py @@ -0,0 +1,28 @@ +from __future__ import annotations +from typing import Optional, TYPE_CHECKING +from attrs import define, field, Factory +from griptape.utils import import_optional_dependency +from griptape.drivers import BaseEmbeddingDriver + +if TYPE_CHECKING: + from ollama import Client + + +@define +class OllamaEmbeddingDriver(BaseEmbeddingDriver): + """ + Attributes: + model: Ollama embedding model name. + host: Optional Ollama host. + client: Ollama `Client`. + """ + + model: str = field(kw_only=True, metadata={"serializable": True}) + host: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) + client: Client = field( + default=Factory(lambda self: import_optional_dependency("ollama").Client(host=self.host), takes_self=True), + kw_only=True, + ) + + def try_embed_chunk(self, chunk: str) -> list[float]: + return list(self.client.embeddings(model=self.model, prompt=chunk)["embedding"]) diff --git a/poetry.lock b/poetry.lock index da5b152d2..1c4be2d3a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -3466,7 +3466,6 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ - {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4abe7fef64914ccfa909bc2ba39739670ecc9e820c83ccc7a6ed414122599b83"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1"}, ] @@ -4710,6 +4709,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -4717,8 +4717,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -4735,6 +4742,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -4742,6 +4750,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -6517,6 +6526,7 @@ drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] drivers-embedding-google = ["google-generativeai"] drivers-embedding-huggingface = ["huggingface-hub", "transformers"] +drivers-embedding-ollama = ["ollama"] drivers-embedding-voyageai = ["voyageai"] drivers-event-listener-amazon-iot = ["boto3"] drivers-event-listener-amazon-sqs = ["boto3"] @@ -6555,4 +6565,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a38d0f0671ff5deb42783721f4ce103e670a689f618e950451a807921f5d7139" +content-hash = "b0688b6e39e07dce28c6609067b46e5047c56c7428ca11f626ee862e3c8daf20" diff --git a/pyproject.toml b/pyproject.toml index ffcba09af..c74e703b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,6 +96,7 @@ drivers-embedding-huggingface = ["huggingface-hub", "transformers"] drivers-embedding-voyageai = ["voyageai"] drivers-embedding-google = ["google-generativeai"] drivers-embedding-cohere = ["cohere"] +drivers-embedding-ollama = ["ollama"] drivers-web-scraper-trafilatura = ["trafilatura"] drivers-web-scraper-markdownify = ["playwright", "beautifulsoup4", "markdownify"] diff --git a/tests/unit/drivers/embedding/test_ollama_embedding_driver.py b/tests/unit/drivers/embedding/test_ollama_embedding_driver.py new file mode 100644 index 000000000..3886ab874 --- /dev/null +++ b/tests/unit/drivers/embedding/test_ollama_embedding_driver.py @@ -0,0 +1,18 @@ +import pytest +from griptape.drivers import OllamaEmbeddingDriver + + +class TestOllamaEmbeddingDriver: + @pytest.fixture(autouse=True) + def mock_client(self, mocker): + mock_client = mocker.patch("ollama.Client") + + mock_client.return_value.embeddings.return_value = {"embedding": [0, 1, 0]} + + return mock_client + + def test_init(self): + assert OllamaEmbeddingDriver(model="foo") + + def test_try_embed_chunk(self): + assert OllamaEmbeddingDriver(model="foo").try_embed_chunk("foobar") == [0, 1, 0] From c668f3dfcd6bfd14a5f95f87eee5e978b7cc11f1 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 10 Jul 2024 13:02:10 -0700 Subject: [PATCH 49/87] Don't Send Empty System Content to Prompt Task (#956) --- CHANGELOG.md | 5 +++++ docs/griptape-framework/structures/agents.md | 2 +- docs/griptape-framework/structures/tasks.md | 2 +- griptape/tasks/prompt_task.py | 4 +++- tests/unit/structures/test_agent.py | 4 ++-- tests/unit/structures/test_pipeline.py | 4 ++-- tests/unit/tasks/test_prompt_task.py | 18 ++++++++++++++++++ 7 files changed, 32 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e34ac3a7..30620d482 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.28.1] - 2024-07-10 + +### Fixed +- Sending empty system content in `PromptTask`. + ## [0.28.0] - 2024-07-09 ### Added - `RagEngine` is an abstraction for implementing modular RAG pipelines. diff --git a/docs/griptape-framework/structures/agents.md b/docs/griptape-framework/structures/agents.md index b36db72d3..581e72082 100644 --- a/docs/griptape-framework/structures/agents.md +++ b/docs/griptape-framework/structures/agents.md @@ -1,7 +1,7 @@ ## Overview An [Agent](../../reference/griptape/structures/agent.md) is the quickest way to get started with Griptape. -Agents take in [tools](../../reference/griptape/structures/agent.md#griptape.structures.agent.Agent.tools) and [input_template](../../reference/griptape/structures/agent.md#griptape.structures.agent.Agent.input_template) +Agents take in [tools](../../reference/griptape/structures/agent.md#griptape.structures.agent.Agent.tools) and [input](../../reference/griptape/structures/agent.md#griptape.structures.agent.Agent.input) directly, which the agent uses to dynamically determine whether to use a [Prompt Task](./tasks.md#prompt-task) or [Toolkit Task](./tasks.md#toolkit-task). If [tools](../../reference/griptape/structures/agent.md#griptape.structures.agent.Agent.tools) are passed provided to the Agent, a [Toolkit Task](./tasks.md#toolkit-task) will be used. If no [tools](../../reference/griptape/structures/agent.md#griptape.structures.agent.Agent.tools) diff --git a/docs/griptape-framework/structures/tasks.md b/docs/griptape-framework/structures/tasks.md index b839b2910..ff5f7e5e4 100644 --- a/docs/griptape-framework/structures/tasks.md +++ b/docs/griptape-framework/structures/tasks.md @@ -98,7 +98,7 @@ agent = Agent() with open("tests/resources/mountain.jpg", "rb") as f: image_artifact = ImageLoader().load(f.read()) -agent.run(["What's in this image?", image_artifact]) +agent.run([image_artifact, "What's in this image?"]) ``` ``` diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index 955855e3d..c428e092d 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -42,7 +42,9 @@ def prompt_stack(self) -> PromptStack: stack = PromptStack() memory = self.structure.conversation_memory - stack.add_system_message(self.generate_system_template(self)) + system_template = self.generate_system_template(self) + if system_template: + stack.add_system_message(system_template) stack.add_user_message(self.input) diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index 5dfcbc6d7..baceac825 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -160,7 +160,7 @@ def test_add_tasks(self): assert True def test_prompt_stack_without_memory(self): - agent = Agent(prompt_driver=MockPromptDriver(), conversation_memory=None) + agent = Agent(prompt_driver=MockPromptDriver(), conversation_memory=None, rules=[Rule("test")]) task1 = PromptTask("test") @@ -177,7 +177,7 @@ def test_prompt_stack_without_memory(self): assert len(task1.prompt_stack.messages) == 3 def test_prompt_stack_with_memory(self): - agent = Agent(prompt_driver=MockPromptDriver(), conversation_memory=ConversationMemory()) + agent = Agent(prompt_driver=MockPromptDriver(), conversation_memory=ConversationMemory(), rules=[Rule("test")]) task1 = PromptTask("test") diff --git a/tests/unit/structures/test_pipeline.py b/tests/unit/structures/test_pipeline.py index 99c4141bf..e63937a62 100644 --- a/tests/unit/structures/test_pipeline.py +++ b/tests/unit/structures/test_pipeline.py @@ -270,7 +270,7 @@ def test_insert_task_at_end(self): assert [child.id for child in third_task.children] == [] def test_prompt_stack_without_memory(self): - pipeline = Pipeline(conversation_memory=None, prompt_driver=MockPromptDriver()) + pipeline = Pipeline(conversation_memory=None, prompt_driver=MockPromptDriver(), rules=[Rule("test")]) task1 = PromptTask("test") task2 = PromptTask("test") @@ -291,7 +291,7 @@ def test_prompt_stack_without_memory(self): assert len(task2.prompt_stack.messages) == 3 def test_prompt_stack_with_memory(self): - pipeline = Pipeline(prompt_driver=MockPromptDriver()) + pipeline = Pipeline(prompt_driver=MockPromptDriver(), rules=[Rule("test")]) task1 = PromptTask("test") task2 = PromptTask("test") diff --git a/tests/unit/tasks/test_prompt_task.py b/tests/unit/tasks/test_prompt_task.py index 3a02309d3..7f9cb3302 100644 --- a/tests/unit/tasks/test_prompt_task.py +++ b/tests/unit/tasks/test_prompt_task.py @@ -4,6 +4,7 @@ from griptape.artifacts.text_artifact import TextArtifact from tests.mocks.mock_structure_config import MockStructureConfig from griptape.tasks import PromptTask +from griptape.rules import Rule from tests.mocks.mock_prompt_driver import MockPromptDriver from griptape.structures import Pipeline @@ -122,3 +123,20 @@ def test_input(self): task = PromptTask({"default": "test"}) assert task.input.value == str({"default": "test"}) + + def test_prompt_stack(self): + task = PromptTask("{{ test }}", context={"test": "test value"}, rules=[Rule("test rule")]) + + Pipeline().add_task(task) + + assert len(task.prompt_stack.messages) == 2 + assert task.prompt_stack.messages[0].is_system() + assert task.prompt_stack.messages[1].is_user() + + def test_prompt_stack_empty_system_content(self): + task = PromptTask("{{ test }}", context={"test": "test value"}) + + Pipeline().add_task(task) + + assert len(task.prompt_stack.messages) == 1 + assert task.prompt_stack.messages[0].is_user() From 44efeef4e56ff1bc5b308488374ecc3b91fb29ed Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 10 Jul 2024 13:18:18 -0700 Subject: [PATCH 50/87] Update duckduckgo (#957) --- CHANGELOG.md | 1 + poetry.lock | 177 ++++++++++++++++++------------------------------- pyproject.toml | 2 +- 3 files changed, 67 insertions(+), 113 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30620d482..816c0707c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Sending empty system content in `PromptTask`. +- Throttling issues with `DuckDuckGoWebSearchDriver`. ## [0.28.0] - 2024-07-09 ### Added diff --git a/poetry.lock b/poetry.lock index da5b152d2..2de802e72 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1234,22 +1234,21 @@ files = [ [[package]] name = "duckduckgo-search" -version = "6.1.7" +version = "6.1.12" description = "Search for words, documents, images, news, maps and text translation using the DuckDuckGo.com search engine." optional = true python-versions = ">=3.8" files = [ - {file = "duckduckgo_search-6.1.7-py3-none-any.whl", hash = "sha256:ec7d5becb8c392c0293ff9464938c1014896e1e14725c05adc306290a636fab2"}, - {file = "duckduckgo_search-6.1.7.tar.gz", hash = "sha256:c6fd8ba17fe9cd0a4f32e5b96984e959c3da865f9c2864bfcf82bf7ff9b7e8f0"}, + {file = "duckduckgo_search-6.1.12-py3-none-any.whl", hash = "sha256:1a3c674de4a9307fe7a05b76726c2bf00d8a97c408ff443d07d7c7a8ac264ed2"}, + {file = "duckduckgo_search-6.1.12.tar.gz", hash = "sha256:6e16ddd54ebfa6567702bd371a95d396e54ad7ace2edd1cb7f4f565547eb065c"}, ] [package.dependencies] click = ">=8.1.7" -orjson = ">=3.10.5" -pyreqwest-impersonate = ">=0.4.8" +pyreqwest-impersonate = ">=0.4.9" [package.extras] -dev = ["mypy (>=1.10.0)", "pytest (>=8.2.2)", "pytest-asyncio (>=0.23.7)", "ruff (>=0.4.8)"] +dev = ["mypy (>=1.10.1)", "pytest (>=8.2.2)", "pytest-asyncio (>=0.23.7)", "ruff (>=0.5.0)"] lxml = ["lxml (>=5.2.2)"] [[package]] @@ -3466,7 +3465,6 @@ description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ - {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_aarch64.whl", hash = "sha256:4abe7fef64914ccfa909bc2ba39739670ecc9e820c83ccc7a6ed414122599b83"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57"}, {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1"}, ] @@ -3543,61 +3541,6 @@ develop = ["black", "botocore", "coverage (<8.0.0)", "jinja2", "mock", "myst-par docs = ["aiohttp (>=3,<4)", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] kerberos = ["requests-kerberos"] -[[package]] -name = "orjson" -version = "3.10.5" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = true -python-versions = ">=3.8" -files = [ - {file = "orjson-3.10.5-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:545d493c1f560d5ccfc134803ceb8955a14c3fcb47bbb4b2fee0232646d0b932"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4324929c2dd917598212bfd554757feca3e5e0fa60da08be11b4aa8b90013c1"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c13ca5e2ddded0ce6a927ea5a9f27cae77eee4c75547b4297252cb20c4d30e6"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6c8e30adfa52c025f042a87f450a6b9ea29649d828e0fec4858ed5e6caecf63"}, - {file = "orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338fd4f071b242f26e9ca802f443edc588fa4ab60bfa81f38beaedf42eda226c"}, - {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6970ed7a3126cfed873c5d21ece1cd5d6f83ca6c9afb71bbae21a0b034588d96"}, - {file = "orjson-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:235dadefb793ad12f7fa11e98a480db1f7c6469ff9e3da5e73c7809c700d746b"}, - {file = "orjson-3.10.5-cp310-none-win32.whl", hash = "sha256:be79e2393679eda6a590638abda16d167754393f5d0850dcbca2d0c3735cebe2"}, - {file = "orjson-3.10.5-cp310-none-win_amd64.whl", hash = "sha256:c4a65310ccb5c9910c47b078ba78e2787cb3878cdded1702ac3d0da71ddc5228"}, - {file = "orjson-3.10.5-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:cdf7365063e80899ae3a697def1277c17a7df7ccfc979990a403dfe77bb54d40"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b68742c469745d0e6ca5724506858f75e2f1e5b59a4315861f9e2b1df77775a"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d10cc1b594951522e35a3463da19e899abe6ca95f3c84c69e9e901e0bd93d38"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcbe82b35d1ac43b0d84072408330fd3295c2896973112d495e7234f7e3da2e1"}, - {file = "orjson-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10c0eb7e0c75e1e486c7563fe231b40fdd658a035ae125c6ba651ca3b07936f5"}, - {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:53ed1c879b10de56f35daf06dbc4a0d9a5db98f6ee853c2dbd3ee9d13e6f302f"}, - {file = "orjson-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:099e81a5975237fda3100f918839af95f42f981447ba8f47adb7b6a3cdb078fa"}, - {file = "orjson-3.10.5-cp311-none-win32.whl", hash = "sha256:1146bf85ea37ac421594107195db8bc77104f74bc83e8ee21a2e58596bfb2f04"}, - {file = "orjson-3.10.5-cp311-none-win_amd64.whl", hash = "sha256:36a10f43c5f3a55c2f680efe07aa93ef4a342d2960dd2b1b7ea2dd764fe4a37c"}, - {file = "orjson-3.10.5-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:68f85ecae7af14a585a563ac741b0547a3f291de81cd1e20903e79f25170458f"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28afa96f496474ce60d3340fe8d9a263aa93ea01201cd2bad844c45cd21f5268"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9cd684927af3e11b6e754df80b9ffafd9fb6adcaa9d3e8fdd5891be5a5cad51e"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d21b9983da032505f7050795e98b5d9eee0df903258951566ecc358f6696969"}, - {file = "orjson-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ad1de7fef79736dde8c3554e75361ec351158a906d747bd901a52a5c9c8d24b"}, - {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d97531cdfe9bdd76d492e69800afd97e5930cb0da6a825646667b2c6c6c0211"}, - {file = "orjson-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d69858c32f09c3e1ce44b617b3ebba1aba030e777000ebdf72b0d8e365d0b2b3"}, - {file = "orjson-3.10.5-cp312-none-win32.whl", hash = "sha256:64c9cc089f127e5875901ac05e5c25aa13cfa5dbbbd9602bda51e5c611d6e3e2"}, - {file = "orjson-3.10.5-cp312-none-win_amd64.whl", hash = "sha256:b2efbd67feff8c1f7728937c0d7f6ca8c25ec81373dc8db4ef394c1d93d13dc5"}, - {file = "orjson-3.10.5-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:03b565c3b93f5d6e001db48b747d31ea3819b89abf041ee10ac6988886d18e01"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:584c902ec19ab7928fd5add1783c909094cc53f31ac7acfada817b0847975f26"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a35455cc0b0b3a1eaf67224035f5388591ec72b9b6136d66b49a553ce9eb1e6"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1670fe88b116c2745a3a30b0f099b699a02bb3482c2591514baf5433819e4f4d"}, - {file = "orjson-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185c394ef45b18b9a7d8e8f333606e2e8194a50c6e3c664215aae8cf42c5385e"}, - {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ca0b3a94ac8d3886c9581b9f9de3ce858263865fdaa383fbc31c310b9eac07c9"}, - {file = "orjson-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dfc91d4720d48e2a709e9c368d5125b4b5899dced34b5400c3837dadc7d6271b"}, - {file = "orjson-3.10.5-cp38-none-win32.whl", hash = "sha256:c05f16701ab2a4ca146d0bca950af254cb7c02f3c01fca8efbbad82d23b3d9d4"}, - {file = "orjson-3.10.5-cp38-none-win_amd64.whl", hash = "sha256:8a11d459338f96a9aa7f232ba95679fc0c7cedbd1b990d736467894210205c09"}, - {file = "orjson-3.10.5-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:85c89131d7b3218db1b24c4abecea92fd6c7f9fab87441cfc342d3acc725d807"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66215277a230c456f9038d5e2d84778141643207f85336ef8d2a9da26bd7ca"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:51bbcdea96cdefa4a9b4461e690c75ad4e33796530d182bdd5c38980202c134a"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dbead71dbe65f959b7bd8cf91e0e11d5338033eba34c114f69078d59827ee139"}, - {file = "orjson-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df58d206e78c40da118a8c14fc189207fffdcb1f21b3b4c9c0c18e839b5a214"}, - {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c4057c3b511bb8aef605616bd3f1f002a697c7e4da6adf095ca5b84c0fd43595"}, - {file = "orjson-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b39e006b00c57125ab974362e740c14a0c6a66ff695bff44615dcf4a70ce2b86"}, - {file = "orjson-3.10.5-cp39-none-win32.whl", hash = "sha256:eded5138cc565a9d618e111c6d5c2547bbdd951114eb822f7f6309e04db0fb47"}, - {file = "orjson-3.10.5-cp39-none-win_amd64.whl", hash = "sha256:cc28e90a7cae7fcba2493953cff61da5a52950e78dc2dacfe931a317ee3d8de7"}, - {file = "orjson-3.10.5.tar.gz", hash = "sha256:7a5baef8a4284405d96c90c7c62b755e9ef1ada84c2406c24a9ebec86b89f46d"}, -] - [[package]] name = "packaging" version = "24.0" @@ -4453,59 +4396,59 @@ image = ["Pillow (>=8.0.0)"] [[package]] name = "pyreqwest-impersonate" -version = "0.4.8" +version = "0.4.9" description = "HTTP client that can impersonate web browsers, mimicking their headers and `TLS/JA3/JA4/HTTP2` fingerprints" optional = true python-versions = ">=3.8" files = [ - {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:45cad57afe4e6f56078ed9a7a90d0dc839d19d3e7a70175c80af21017f383bfb"}, - {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1986600253baf38f25fd07b8bdc1903359c26e5d34beb7d7d084845554b5664d"}, - {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cca4e6e59b9ad0cd20bad6caed3ac96992cd9c1d3126ecdfcab2c0ac2b75376"}, - {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ab6b32544491ee655264dab86fc8a58e47c4f87d196b28022d4007faf971a50"}, - {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:64bd6299e7fc888bb7f7292cf3e29504c406e5d5d04afd37ca994ab8142d8ee4"}, - {file = "pyreqwest_impersonate-0.4.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e914b650dd953b8d9b24ef56aa4ecbfc16e399227b68accd818f8bf159e0c558"}, - {file = "pyreqwest_impersonate-0.4.8-cp310-none-win_amd64.whl", hash = "sha256:cb56a2149b0c4548a8e0158b071a943f33dae9b717f92b5c9ac34ccd1f5a958c"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f62620e023490902feca0109f306e122e427feff7d59e03ecd22c69a89452367"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:08d4c01d76da88cfe3d7d03b311b375ce3fb5a59130f93f0637bb755d6e56ff1"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6524e276bc460176c79d7ba4b9131d9db73c534586660371ebdf067749252a33"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22863bc0aaf02ca2f5d76c8130929ae680b7d82dfc1c28c1ed5f306ff626928"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8cc82d57f6a91037e64a7aa9122f909576ef2a141a42ce599958ef9f8c4bc033"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:da8a053308210e44fd8349f07f45442a0691ac932f2881e98b05cf9ac404b091"}, - {file = "pyreqwest_impersonate-0.4.8-cp311-none-win_amd64.whl", hash = "sha256:4baf3916c14364a815a64ead7f728afb61b37541933b2771f18dbb245029bb55"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:78db05deed0b32c9c75f2b3168a3a9b7d5e36487b218cb839bfe7e2a143450cb"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9af9446d605903c2b4e94621a9093f8d8a403729bc9cbfbcb62929f8238c838f"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c55890181d8d81e66cac25a95e215dc9680645d01e9091b64449d5407ad9bc6"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69344e7ae9964502a8693da7ad77ebc3e1418ee197e2e394bc23c5d4970772a"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b5db5c957a10d8cc2815085ba0b8fe09245b2f94c2225d9653a854a03b4217e1"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:03c19c21f63f9c91c590c4bbcc32cc2d8066b508c683a1d163b8c7d9816a01d5"}, - {file = "pyreqwest_impersonate-0.4.8-cp312-none-win_amd64.whl", hash = "sha256:0230610779129f74ff802c744643ce7589b1d07cba21d046fe3b574281c29581"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b8cb9471ab4b2fa7e80d3ac4e580249ff988d782f2938ad1f0428433652b170d"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8081a5ace2658be91519902bde9ddc5f94e1f850a39be196007a25e3da5bbfdc"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69eababfa3200459276acd780a0f3eaf41d1fe7c02bd169e714cba422055b5b9"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:632957fa671ebb841166e40913015de457225cb73600ef250c436c280e68bf45"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:2ce7ddef334b4e5c68f5ea1da1d65f686b8d84f4443059d128e0f069d3fa499a"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:6ce333d450b158d582e36317089a006440b4e66739a8e8849d170e4cb15e8c8d"}, - {file = "pyreqwest_impersonate-0.4.8-cp38-none-win_amd64.whl", hash = "sha256:9d9c85ce19db92362854f534807e470f03e905f283a7de6826dc79b790a8788e"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:2503277f2a95a30e28e498570e2ed03ef4302f873054e8e21d6c0e607cbbc1d1"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8260395ef4ddae325e8b30cef0391adde7bd35e1a1decf8c729e26391f09b52d"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d8066b46d82bbaff5402d767e2f13d3449b8191c37bf8283e91d301a7159869"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9c42f6343cfbd6663fb53edc9eb9feb4ebf6186b284e22368adc1eeb6a33854"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ff534f491a059e74fb7f994876df86078b4b125dbecc53c098a298ecd55fa9c6"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5b8fbf73b3ac513ddadafd338d61f79cd2370f0691d9175b2b92a45920920d6b"}, - {file = "pyreqwest_impersonate-0.4.8-cp39-none-win_amd64.whl", hash = "sha256:a26447c82665d0e361207c1a15e56b0ca54974aa6c1fdfa18c68f908dec78cbe"}, - {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:24a16b8d55309f0af0db9d04ff442b0c91afccf078a94809e7c3a71747a5c214"}, - {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c8fada56465fc19179404cc9d5d5e1064f5dfe27405cb052f57a5b4fe06aed1"}, - {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:a3d48d5abc146fd804395713427d944757a99254350e6a651e7d776818074aee"}, - {file = "pyreqwest_impersonate-0.4.8-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:475829fe9994c66258157a8d4adb1c038f44f79f901208ba656d547842337227"}, - {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5ef1ec0e97623bc0e18469418cc4dd2c59a2d5fddcae944de61e13c0b46f910e"}, - {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91857b196de89e9b36d3f8629aa8772c0bbe7efef8334fe266956b1c192ec31c"}, - {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:63831e407487b8a21bb51f97cd86a616c291d5138f8caec16ab6019cf6423935"}, - {file = "pyreqwest_impersonate-0.4.8-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:c30e61de93bcd0a9d3ca226b1ae5475002afde61e9d85018a6a4a040eeb86567"}, - {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6c72c37b03bce9900f5dbb4f476af17253ec60c13bf7a7259f71a8dc1b036cb"}, - {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f1096165741b5c2178ab15b0eb09b5de16dd39b1cc135767d72471f0a69ce"}, - {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:70c940c0e4ef335e22a6c705b01f286ee44780b5909065d212d94d82ea2580cb"}, - {file = "pyreqwest_impersonate-0.4.8-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:81c06f21757602d85f16dbc1cbaee1121cd65455f65aed4c048b7dcda7be85c4"}, - {file = "pyreqwest_impersonate-0.4.8.tar.gz", hash = "sha256:1eba11d47bd17244c64fec1502cc26ee66cc5c8a3be131e408101ae2b455e5bc"}, + {file = "pyreqwest_impersonate-0.4.9-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a229f56575d992df0c520d93408b4b6b660b304387af06208e7b97d739cce2ff"}, + {file = "pyreqwest_impersonate-0.4.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c00dbfd0ed878bed231384cd0c823d71a42220ae73c6d982b6fe77d2870338ca"}, + {file = "pyreqwest_impersonate-0.4.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d4e6ce0e48b73740f08b1aa69cdbded5d66f4eec327d5eaf2ac42a4fce1a008"}, + {file = "pyreqwest_impersonate-0.4.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:690a5c5615b33cbab340e3a4247256ede157ebf39a02f563cff5356bf61c0c51"}, + {file = "pyreqwest_impersonate-0.4.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:7231511ee14faee27b90a84ec74e15515b7e2d1c389710698660765eaed6e2fd"}, + {file = "pyreqwest_impersonate-0.4.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2fdbe8e146e595c02fa0afb776d70f9e3b351122e2de9af15934b83f3a548ecd"}, + {file = "pyreqwest_impersonate-0.4.9-cp310-none-win_amd64.whl", hash = "sha256:982b0e53db24c084675a056944dd769aa07cd1378abf972927f3f1afb23e08b0"}, + {file = "pyreqwest_impersonate-0.4.9-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:60b1102b8aec7bbf91e0f7b8bbc3507776731a9acc6844de764911e8d64f7dd2"}, + {file = "pyreqwest_impersonate-0.4.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37150478157e683374517d4c0eae0f991b8f5280067a8ee042b6a72fec088843"}, + {file = "pyreqwest_impersonate-0.4.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccc77cd1cdae22dad7549a4e9a1a4630619c2ff443add1b28c7d607accda81eb"}, + {file = "pyreqwest_impersonate-0.4.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83e99e627d13f1f60d71ce2c2a2b03e1c7f57e8f6a73bde2827ff97cb96f1683"}, + {file = "pyreqwest_impersonate-0.4.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:72d1adb73264db8c5e24d073d558a895d6690d13a5e38fd857b8b01c33fcbabf"}, + {file = "pyreqwest_impersonate-0.4.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6253bd8a104316bbece0e6c658d28292f0bf37a99cccfaf476470b98252d185b"}, + {file = "pyreqwest_impersonate-0.4.9-cp311-none-win_amd64.whl", hash = "sha256:7e25628a900236fc76320e790fce90e5502371994523c476af2b1c938382f5fa"}, + {file = "pyreqwest_impersonate-0.4.9-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:57e1e7f3bfc175c3229947cdd2b26564bcea2923135b8dec8ab157609e201a7c"}, + {file = "pyreqwest_impersonate-0.4.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3aeb1c834f54fe685d3c7c0bec65dd981bd988fa3725ee3c7b5656eb7c44a1f7"}, + {file = "pyreqwest_impersonate-0.4.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27bc384f18099573817d7ed68d12eb67d33dfc5d2b30ab2ac5a69cdf19c22b6f"}, + {file = "pyreqwest_impersonate-0.4.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd604444ddf86ed222b49dd5e3f050c4c0e980dd7be0b3ea0f208fb70544c4b6"}, + {file = "pyreqwest_impersonate-0.4.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5206dc7311081accf5b7d021c9e0e68219fd7bb35b0cd755b2d72c3ebfa41842"}, + {file = "pyreqwest_impersonate-0.4.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76802f0738c2d00bb4e057938ec048c4c7c4efc5c44f04b9d877ad4419b21ee8"}, + {file = "pyreqwest_impersonate-0.4.9-cp312-none-win_amd64.whl", hash = "sha256:7cf94f6365bc144f787658e844f94dad38107fb9ff61d65079fb6510447777fe"}, + {file = "pyreqwest_impersonate-0.4.9-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:66e92bd868146028dac1ef9cd2b4aac57e7e6cbd8806fa8a4c77ac5becf396e1"}, + {file = "pyreqwest_impersonate-0.4.9-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dc3ff7ac332879e40301d737b3ec1f3691b1de7492728bea26e75e26d05f89ec"}, + {file = "pyreqwest_impersonate-0.4.9-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c9e9eba83620852d4253023e50e3436726aee16e2de94afbd468da4373830dc"}, + {file = "pyreqwest_impersonate-0.4.9-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d6b47d403c63b461a97efa2aed668f0f06ed26cf61c23d7d6dab4f5a0c81ffc"}, + {file = "pyreqwest_impersonate-0.4.9-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:88f695a01e8699ec3a1547d793617b9fd00f810c05c2b4dc0d1472c7f12eed97"}, + {file = "pyreqwest_impersonate-0.4.9-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:abb4fbfaa1a3c3adeb7f46baa1d67663af85ab24f2b4cdd15a668ddc6be3a375"}, + {file = "pyreqwest_impersonate-0.4.9-cp38-none-win_amd64.whl", hash = "sha256:884c1399fe0157dcd0a5a71e3600910df50faa0108c64602d47c15e75b32e60b"}, + {file = "pyreqwest_impersonate-0.4.9-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bf5cd99276207510d64b48eff5602e12f049754d3b0f1194a024e1a080a61d3d"}, + {file = "pyreqwest_impersonate-0.4.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:029eea1d386d12856da767d685169835f0b0c025ae312c1ee7bc0d8cb47a7d3d"}, + {file = "pyreqwest_impersonate-0.4.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1bfb8795fe0a46aee883abcf510a9ecdb4e9acf75c3a5a23571276f555f5e88"}, + {file = "pyreqwest_impersonate-0.4.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fe35ce48e7e6b570304ee15915da0e6fab82dcae2b7a1d1a92593b522ebe852"}, + {file = "pyreqwest_impersonate-0.4.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:dfa377a842bd2e73d1f201bfc33194dd98c148372409d376f6d57efe338ff0eb"}, + {file = "pyreqwest_impersonate-0.4.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d46880e68eb779cd071648e94a7ec50b3b77a28210f218be407eda1b0c8df343"}, + {file = "pyreqwest_impersonate-0.4.9-cp39-none-win_amd64.whl", hash = "sha256:ac431e4a94f8529a19a396750d78c66cc4fa11a8cc61d4bed7f0e0295a9394a9"}, + {file = "pyreqwest_impersonate-0.4.9-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12fd04d8da4d23ab5720402fd9f3b6944fb388c19952f2ec9121b46ac1f74616"}, + {file = "pyreqwest_impersonate-0.4.9-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b52df560d78681cde2fbc39bee547a42a79c8fd33655b79618835ecc412e6933"}, + {file = "pyreqwest_impersonate-0.4.9-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e1a2828942f9d589ee6161496444a380d3305e78bda25ff63e4f993b0545b193"}, + {file = "pyreqwest_impersonate-0.4.9-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:beebedf6d8c0d5fdee9ae15bc64a74e51b35f98eb0d049bf2db067702fbf4e53"}, + {file = "pyreqwest_impersonate-0.4.9-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a3d47dea1f46410b58ab60795b5818c8c99d901f6c93fbb6a9d23fa55adb2b1"}, + {file = "pyreqwest_impersonate-0.4.9-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7bb871adc5d12b2bcbb5af167384d49fc4e7e5e07d12cf912b931149163df724"}, + {file = "pyreqwest_impersonate-0.4.9-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:d1b0b5556d2bd14a4ffa32654291fe2a9ef1eaac35b5514d9220e7e333a6c727"}, + {file = "pyreqwest_impersonate-0.4.9-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:5d50feaec78c06d51e1dd65cdbe80a1fc62ff93c8114555482f8a8cc5fe14895"}, + {file = "pyreqwest_impersonate-0.4.9-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2a9cfc41917200d8eee61b87a5668abe7d1f924a55b7437065540edf613beed"}, + {file = "pyreqwest_impersonate-0.4.9-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8106e3df0c1dca4df99e0f998f0e085ea3e1facfaa5afc268160a496ddf7256f"}, + {file = "pyreqwest_impersonate-0.4.9-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ff66bb7dc6b1f52cf950b5e9cb0e53baffd1a15da595fd1ef933cd9e36396403"}, + {file = "pyreqwest_impersonate-0.4.9-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:39f2a3ed17cf08098dc637459e88fb86d3fa7bdf9502659c82218be75651649c"}, + {file = "pyreqwest_impersonate-0.4.9.tar.gz", hash = "sha256:4ec8df7fe813e89f61e814c5ef75f6fd71164c8e26299c1a42dcd0d42f0bc96c"}, ] [package.extras] @@ -4710,6 +4653,7 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, + {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -4717,8 +4661,15 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, + {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, + {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, + {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, + {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, + {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -4735,6 +4686,7 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, + {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -4742,6 +4694,7 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, + {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -6555,4 +6508,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a38d0f0671ff5deb42783721f4ce103e670a689f618e950451a807921f5d7139" +content-hash = "9d51d83be6a0b24045d93d5213c91808a993bd60d3d9f3c14ebcb58aea89422e" diff --git a/pyproject.toml b/pyproject.toml index ffcba09af..6180365b8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,7 +55,7 @@ torch = {version = "^2.3.0", optional = true} qdrant-client = { version = ">=1.9.1", optional = true } pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} -duckduckgo-search = {version = "^6.1.6", optional = true} +duckduckgo-search = {version = "^6.1.12", optional = true} # loaders pandas = {version = "^1.3", optional = true} From 058d7e7c654fe7936ddc7ea24ffdef37295b13e4 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 10 Jul 2024 13:52:39 -0700 Subject: [PATCH 51/87] Version bump v0.28.1 (#958) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 6180365b8..9090da332 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "griptape" -version = "0.28.0" +version = "0.28.1" description = "Modular Python framework for LLM workflows, tools, memory, and data." authors = ["Griptape "] license = "Apache 2.0" From 8fa35a55ff04a0858485229db495aa84c63e9d4e Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 10 Jul 2024 15:00:50 -0700 Subject: [PATCH 52/87] Feature/native functions (#867) --- CHANGELOG.md | 1 + .../drivers/prompt-drivers.md | 18 + docs/griptape-framework/misc/events.md | 2 +- docs/griptape-framework/tools/index.md | 7 +- griptape/artifacts/__init__.py | 2 + griptape/artifacts/action_artifact.py | 18 + griptape/common/__init__.py | 12 + griptape/common/actions/__init__.py | 0 griptape/common/actions/base_action.py | 5 + griptape/common/actions/tool_action.py | 54 +++ .../action_call_delta_message_content.py | 31 ++ .../contents/action_call_message_content.py | 47 +++ .../contents/action_result_message_content.py | 18 + .../contents/base_message_content.py | 10 +- .../prompt_stack/messages/delta_message.py | 6 +- .../common/prompt_stack/messages/message.py | 18 +- griptape/common/prompt_stack/prompt_stack.py | 33 +- griptape/config/anthropic_structure_config.py | 2 +- .../prompt/amazon_bedrock_prompt_driver.py | 178 +++++++-- .../drivers/prompt/anthropic_prompt_driver.py | 152 +++++-- griptape/drivers/prompt/base_prompt_driver.py | 41 +- .../drivers/prompt/cohere_prompt_driver.py | 188 +++++++-- .../drivers/prompt/google_prompt_driver.py | 194 ++++++--- .../prompt/openai_chat_prompt_driver.py | 180 +++++++-- griptape/schemas/base_schema.py | 11 +- griptape/tasks/actions_subtask.py | 206 +++++----- griptape/tasks/tool_task.py | 62 +-- griptape/tasks/toolkit_task.py | 46 ++- griptape/templates/tasks/tool_task/system.j2 | 7 +- .../templates/tasks/toolkit_task/system.j2 | 14 +- griptape/tools/base_tool.py | 11 +- griptape/utils/__init__.py | 3 +- griptape/utils/dict_utils.py | 7 + poetry.lock | 14 +- pyproject.toml | 2 +- tests/unit/artifacts/test_action_artifact.py | 53 +++ tests/unit/common/__init__.py | 0 .../test_action_call_delta_message_content.py | 25 ++ .../test_action_call_message_content.py | 55 +++ .../test_action_result_message_content.py | 18 + .../contents/test_base_message_content.py | 17 + .../contents/test_image_message_content.py | 12 + .../test_text_delta_message_content.py | 6 + .../contents/test_text_message_content.py | 15 + tests/unit/common/test_action.py | 33 ++ tests/unit/common/test_prompt_stack.py | 90 +++++ .../test_amazon_bedrock_structure_config.py | 4 + .../config/test_anthropic_structure_config.py | 3 +- .../test_azure_openai_structure_config.py | 1 + .../config/test_cohere_structure_config.py | 2 + .../config/test_google_structure_config.py | 2 + .../config/test_openai_structure_config.py | 1 + tests/unit/config/test_structure_config.py | 8 +- .../test_amazon_bedrock_prompt_driver.py | 317 ++++++++++++++- .../prompt/test_anthropic_prompt_driver.py | 375 ++++++++++++++---- .../test_azure_openai_chat_prompt_driver.py | 96 ++++- .../prompt/test_cohere_prompt_driver.py | 175 +++++++- .../prompt/test_google_prompt_driver.py | 225 ++++++++--- .../test_hugging_face_hub_prompt_driver.py | 3 +- .../prompt/test_openai_chat_prompt_driver.py | 267 +++++++++++-- tests/unit/tasks/test_actions_subtask.py | 75 +++- tests/unit/tasks/test_toolkit_task.py | 11 +- tests/unit/tools/test_base_tool.py | 7 +- tests/unit/utils/test_dict_utils.py | 9 +- 64 files changed, 2930 insertions(+), 575 deletions(-) create mode 100644 griptape/artifacts/action_artifact.py create mode 100644 griptape/common/actions/__init__.py create mode 100644 griptape/common/actions/base_action.py create mode 100644 griptape/common/actions/tool_action.py create mode 100644 griptape/common/prompt_stack/contents/action_call_delta_message_content.py create mode 100644 griptape/common/prompt_stack/contents/action_call_message_content.py create mode 100644 griptape/common/prompt_stack/contents/action_result_message_content.py create mode 100644 tests/unit/artifacts/test_action_artifact.py create mode 100644 tests/unit/common/__init__.py create mode 100644 tests/unit/common/contents/test_action_call_delta_message_content.py create mode 100644 tests/unit/common/contents/test_action_call_message_content.py create mode 100644 tests/unit/common/contents/test_action_result_message_content.py create mode 100644 tests/unit/common/contents/test_base_message_content.py create mode 100644 tests/unit/common/contents/test_image_message_content.py create mode 100644 tests/unit/common/contents/test_text_delta_message_content.py create mode 100644 tests/unit/common/contents/test_text_message_content.py create mode 100644 tests/unit/common/test_action.py create mode 100644 tests/unit/common/test_prompt_stack.py diff --git a/CHANGELOG.md b/CHANGELOG.md index d2b2d7998..82eaeef3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased ### Added +- Native function calling support to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AnthropicPromptDriver`, `AmazonBedrockPromptDriver`, `GooglePromptDriver`, and `CoherePromptDriver`. - `OllamaEmbeddingDriver` for generating embeddings with Ollama. ### Changed diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index a846cbb5b..cdb90aef5 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -61,6 +61,9 @@ Griptape offers the following Prompt Drivers for interacting with LLMs. ### OpenAI Chat +!!! info + This driver uses [OpenAi function calling](https://platform.openai.com/docs/guides/function-calling) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. + The [OpenAiChatPromptDriver](../../reference/griptape/drivers/prompt/openai_chat_prompt_driver.md) connects to the [OpenAI Chat](https://platform.openai.com/docs/guides/chat) API. ```python @@ -96,6 +99,9 @@ agent.run("Blue sky at dusk.") ### Azure OpenAI Chat +!!! info + This driver uses [Azure OpenAi function calling](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/function-calling) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. + The [AzureOpenAiChatPromptDriver](../../reference/griptape/drivers/prompt/azure_openai_chat_prompt_driver.md) connects to Azure OpenAI [Chat Completion](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/reference) APIs. ```python @@ -132,6 +138,9 @@ The [CoherePromptDriver](../../reference/griptape/drivers/prompt/cohere_prompt_d !!! info This driver requires the `drivers-prompt-cohere` [extra](../index.md#extras). +!!! info + This driver uses [Cohere tool use](https://docs.cohere.com/docs/tools) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. + ```python import os from griptape.structures import Agent @@ -155,6 +164,9 @@ agent.run('What is the sentiment of this review? Review: "I really enjoyed this !!! info This driver requires the `drivers-prompt-anthropic` [extra](../index.md#extras). +!!! info + This driver uses [Anthropic tool use](https://docs.anthropic.com/en/docs/build-with-claude/tool-use) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. + The [AnthropicPromptDriver](../../reference/griptape/drivers/prompt/anthropic_prompt_driver.md) connects to the Anthropic [Messages](https://docs.anthropic.com/claude/reference/messages_post) API. ```python @@ -180,6 +192,9 @@ agent.run('Where is the best place to see cherry blossums in Japan?') !!! info This driver requires the `drivers-prompt-google` [extra](../index.md#extras). +!!! info + This driver uses [Gemini function calling](https://ai.google.dev/gemini-api/docs/function-calling) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. + The [GooglePromptDriver](../../reference/griptape/drivers/prompt/google_prompt_driver.md) connects to the [Google Generative AI](https://ai.google.dev/tutorials/python_quickstart#generate_text_from_text_inputs) API. ```python @@ -205,6 +220,9 @@ agent.run('Briefly explain how a computer works to a young child.') !!! info This driver requires the `drivers-prompt-amazon-bedrock` [extra](../index.md#extras). +!!! info + This drivers uses [Bedrock tool use](https://docs.aws.amazon.com/bedrock/latest/userguide/tool-use.html) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. + The [AmazonBedrockPromptDriver](../../reference/griptape/drivers/prompt/amazon_bedrock_prompt_driver.md) uses [Amazon Bedrock](https://aws.amazon.com/bedrock/)'s [Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html). All models supported by the Converse API are available for use with this driver. diff --git a/docs/griptape-framework/misc/events.md b/docs/griptape-framework/misc/events.md index 2d3645e94..851b5f382 100644 --- a/docs/griptape-framework/misc/events.md +++ b/docs/griptape-framework/misc/events.md @@ -244,7 +244,7 @@ from griptape.events import BaseEvent, StartPromptEvent, EventListener def handler(event: BaseEvent): if isinstance(event, StartPromptEvent): - print("Prompt Stack PromptStack:") + print("Prompt Stack Messages:") for message in event.prompt_stack.messages: print(f"{message.role}: {message.content}") print("Final Prompt String:") diff --git a/docs/griptape-framework/tools/index.md b/docs/griptape-framework/tools/index.md index 4d604a77c..05fc94501 100644 --- a/docs/griptape-framework/tools/index.md +++ b/docs/griptape-framework/tools/index.md @@ -1,11 +1,10 @@ ## Overview -One of the most powerful features of Griptape is the ability for Toolkit Tasks to generate _chains of thought_ (CoT) and use tools that can interact with the outside world. We use the [ReAct](https://arxiv.org/abs/2210.03629) technique to implement CoT reasoning and acting in the underlying LLMs without using any fine-tuning. - -Griptape implements the reasoning loop in the Toolkit Tasks and integrates Griptape Tools natively. +One of the most powerful features of Griptape is the ability to use tools that can interact with the outside world. +Many of our [Prompt Drivers](../drivers/prompt-drivers.md) leverage the native function calling built into the LLMs. For LLMs that don't support this, Griptape provides its own implementation using the [ReAct](https://arxiv.org/abs/2210.03629) technique. ## Tools -Here is an example of a pipeline using tools: +Here is an example of a Pipeline using Tools: ```python from griptape.tasks import ToolkitTask diff --git a/griptape/artifacts/__init__.py b/griptape/artifacts/__init__.py index 00c19519f..51525f60d 100644 --- a/griptape/artifacts/__init__.py +++ b/griptape/artifacts/__init__.py @@ -9,6 +9,7 @@ from .media_artifact import MediaArtifact from .image_artifact import ImageArtifact from .audio_artifact import AudioArtifact +from .action_artifact import ActionArtifact __all__ = [ @@ -23,4 +24,5 @@ "MediaArtifact", "ImageArtifact", "AudioArtifact", + "ActionArtifact", ] diff --git a/griptape/artifacts/action_artifact.py b/griptape/artifacts/action_artifact.py new file mode 100644 index 000000000..210e24f9f --- /dev/null +++ b/griptape/artifacts/action_artifact.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from attrs import define, field +from typing import TYPE_CHECKING + +from griptape.artifacts import BaseArtifact +from griptape.mixins import SerializableMixin + +if TYPE_CHECKING: + from griptape.common import ToolAction + + +@define() +class ActionArtifact(BaseArtifact, SerializableMixin): + value: ToolAction = field(metadata={"serializable": True}) + + def __add__(self, other: BaseArtifact) -> ActionArtifact: + raise NotImplementedError diff --git a/griptape/common/__init__.py b/griptape/common/__init__.py index 6e357323a..8324bcb9d 100644 --- a/griptape/common/__init__.py +++ b/griptape/common/__init__.py @@ -1,8 +1,14 @@ +from .actions.base_action import BaseAction +from .actions.tool_action import ToolAction + from .prompt_stack.contents.base_message_content import BaseMessageContent from .prompt_stack.contents.base_delta_message_content import BaseDeltaMessageContent from .prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent from .prompt_stack.contents.text_message_content import TextMessageContent from .prompt_stack.contents.image_message_content import ImageMessageContent +from .prompt_stack.contents.action_call_delta_message_content import ActionCallDeltaMessageContent +from .prompt_stack.contents.action_call_message_content import ActionCallMessageContent +from .prompt_stack.contents.action_result_message_content import ActionResultMessageContent from .prompt_stack.messages.base_message import BaseMessage from .prompt_stack.messages.delta_message import DeltaMessage @@ -12,6 +18,7 @@ from .reference import Reference + __all__ = [ "BaseMessage", "BaseDeltaMessageContent", @@ -21,6 +28,11 @@ "TextDeltaMessageContent", "TextMessageContent", "ImageMessageContent", + "ActionCallDeltaMessageContent", + "ActionCallMessageContent", + "ActionResultMessageContent", "PromptStack", "Reference", + "BaseAction", + "ToolAction", ] diff --git a/griptape/common/actions/__init__.py b/griptape/common/actions/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/common/actions/base_action.py b/griptape/common/actions/base_action.py new file mode 100644 index 000000000..6bfda8f30 --- /dev/null +++ b/griptape/common/actions/base_action.py @@ -0,0 +1,5 @@ +from griptape.mixins import SerializableMixin +from abc import ABC + + +class BaseAction(SerializableMixin, ABC): ... diff --git a/griptape/common/actions/tool_action.py b/griptape/common/actions/tool_action.py new file mode 100644 index 000000000..db1e29f74 --- /dev/null +++ b/griptape/common/actions/tool_action.py @@ -0,0 +1,54 @@ +from __future__ import annotations +import json +from typing import TYPE_CHECKING, Optional + +from attrs import define, field + +from griptape.artifacts import BaseArtifact +from griptape.common import BaseAction + +if TYPE_CHECKING: + from griptape.tools import BaseTool + + +@define(kw_only=True) +class ToolAction(BaseAction): + """Represents an instance of an LLM using a Tool. + + Attributes: + tag: The tag (unique identifier) of the action. + name: The name (Tool name) of the action. + path: The path (Tool activity name) of the action. + input: The input (Tool params) of the action. + tool: The matched Tool of the action. + output: The output (Tool result) of the action. + """ + + tag: str = field(metadata={"serializable": True}) + name: str = field(metadata={"serializable": True}) + path: Optional[str] = field(default=None, metadata={"serializable": True}) + input: dict = field(factory=dict, metadata={"serializable": True}) + tool: Optional[BaseTool] = field(default=None) + output: Optional[BaseArtifact] = field(default=None) + + def __str__(self) -> str: + return json.dumps(self.to_dict()) + + def to_native_tool_name(self) -> str: + parts = [self.name] + + if self.path is not None: + parts.append(self.path) + + return "_".join(parts) + + @classmethod + def from_native_tool_name(cls, native_tool_name: str) -> tuple[str, Optional[str]]: + parts = native_tool_name.split("_", 1) + + if len(parts) == 1: + name, path = parts[0], None + else: + name, path = parts + + return name, path diff --git a/griptape/common/prompt_stack/contents/action_call_delta_message_content.py b/griptape/common/prompt_stack/contents/action_call_delta_message_content.py new file mode 100644 index 000000000..5e86aa164 --- /dev/null +++ b/griptape/common/prompt_stack/contents/action_call_delta_message_content.py @@ -0,0 +1,31 @@ +from __future__ import annotations +from attrs import define, field +from typing import Optional + +from griptape.common import BaseDeltaMessageContent + + +@define +class ActionCallDeltaMessageContent(BaseDeltaMessageContent): + tag: Optional[str] = field(default=None, metadata={"serializable": True}) + name: Optional[str] = field(default=None, metadata={"serializable": True}) + path: Optional[str] = field(default=None, metadata={"serializable": True}) + partial_input: Optional[str] = field(default=None, metadata={"serializable": True}) + + def __str__(self) -> str: + parts = [] + + if self.name: + parts.append(self.name) + if self.path: + parts.append(f".{self.path}") + if self.tag: + parts.append(f" ({self.tag})") + + if self.partial_input: + if parts: + parts.append(f" {self.partial_input}") + else: + parts.append(self.partial_input) + + return "".join(parts) diff --git a/griptape/common/prompt_stack/contents/action_call_message_content.py b/griptape/common/prompt_stack/contents/action_call_message_content.py new file mode 100644 index 000000000..9f8082d72 --- /dev/null +++ b/griptape/common/prompt_stack/contents/action_call_message_content.py @@ -0,0 +1,47 @@ +from __future__ import annotations + +import json +from collections.abc import Sequence + +from attrs import define, field + +from griptape.common import ToolAction +from griptape.artifacts import ActionArtifact +from griptape.common import BaseDeltaMessageContent, BaseMessageContent, ActionCallDeltaMessageContent + + +@define +class ActionCallMessageContent(BaseMessageContent): + artifact: ActionArtifact = field(metadata={"serializable": True}) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> ActionCallMessageContent: + action_call_deltas = [delta for delta in deltas if isinstance(delta, ActionCallDeltaMessageContent)] + + tag = None + name = None + path = None + input = "" + + for delta in action_call_deltas: + if delta.tag is not None: + tag = delta.tag + if delta.name is not None: + name = delta.name + if delta.path is not None: + path = delta.path + if delta.partial_input is not None: + input += delta.partial_input + + if tag is not None and name is not None and path is not None: + try: + parsed_input = json.loads(input) + except json.JSONDecodeError as exc: + raise ValueError("Invalid JSON input for ToolAction") from exc + action = ToolAction(tag=tag, name=name, path=path, input=parsed_input) + else: + raise ValueError("Missing required fields for ToolAction") + + artifact = ActionArtifact(value=action) + + return cls(artifact=artifact) diff --git a/griptape/common/prompt_stack/contents/action_result_message_content.py b/griptape/common/prompt_stack/contents/action_result_message_content.py new file mode 100644 index 000000000..871649aea --- /dev/null +++ b/griptape/common/prompt_stack/contents/action_result_message_content.py @@ -0,0 +1,18 @@ +from __future__ import annotations + +from collections.abc import Sequence + +from attrs import define, field + +from griptape.artifacts import BaseArtifact +from griptape.common import BaseDeltaMessageContent, BaseMessageContent, ToolAction + + +@define +class ActionResultMessageContent(BaseMessageContent): + artifact: BaseArtifact = field(metadata={"serializable": True}) + action: ToolAction = field(metadata={"serializable": True}) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> ActionResultMessageContent: + raise NotImplementedError diff --git a/griptape/common/prompt_stack/contents/base_message_content.py b/griptape/common/prompt_stack/contents/base_message_content.py index 28a9e317e..f24f5229b 100644 --- a/griptape/common/prompt_stack/contents/base_message_content.py +++ b/griptape/common/prompt_stack/contents/base_message_content.py @@ -1,5 +1,6 @@ from __future__ import annotations -from abc import ABC + +from abc import ABC, abstractmethod from collections.abc import Sequence from typing import TYPE_CHECKING from attrs import define, field @@ -14,9 +15,6 @@ class BaseMessageContent(ABC, SerializableMixin): artifact: BaseArtifact = field(metadata={"serializable": True}) - def to_text(self) -> str: - return str(self.artifact) - def __str__(self) -> str: return self.artifact.to_text() @@ -26,5 +24,9 @@ def __bool__(self) -> bool: def __len__(self) -> int: return len(self.artifact) + def to_text(self) -> str: + return str(self.artifact) + @classmethod + @abstractmethod def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> BaseMessageContent: ... diff --git a/griptape/common/prompt_stack/messages/delta_message.py b/griptape/common/prompt_stack/messages/delta_message.py index 7ff90b08f..a540d205c 100644 --- a/griptape/common/prompt_stack/messages/delta_message.py +++ b/griptape/common/prompt_stack/messages/delta_message.py @@ -1,10 +1,10 @@ from __future__ import annotations + from typing import Optional from attrs import define, field -from griptape.common.prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent - +from griptape.common import BaseDeltaMessageContent from .base_message import BaseMessage @@ -12,4 +12,4 @@ @define class DeltaMessage(BaseMessage): role: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": True}) - content: Optional[TextDeltaMessageContent] = field(kw_only=True, default=None, metadata={"serializable": True}) + content: Optional[BaseDeltaMessageContent] = field(kw_only=True, default=None, metadata={"serializable": True}) diff --git a/griptape/common/prompt_stack/messages/message.py b/griptape/common/prompt_stack/messages/message.py index fcf6750ea..8bc6f63e2 100644 --- a/griptape/common/prompt_stack/messages/message.py +++ b/griptape/common/prompt_stack/messages/message.py @@ -1,14 +1,16 @@ from __future__ import annotations -from typing import Any +from typing import Any, TypeVar from attrs import define, field -from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact +from griptape.artifacts import TextArtifact, ListArtifact, BaseArtifact from griptape.common import BaseMessageContent, TextMessageContent from .base_message import BaseMessage +T = TypeVar("T", bound=BaseMessageContent) + @define class Message(BaseMessage): @@ -26,6 +28,18 @@ def value(self) -> Any: def __str__(self) -> str: return self.to_text() + def has_all_content_type(self, content_type: type[T]) -> bool: + return all(isinstance(content, content_type) for content in self.content) + + def has_any_content_type(self, content_type: type[T]) -> bool: + return any(isinstance(content, content_type) for content in self.content) + + def get_content_type(self, content_type: type[T]) -> list[T]: + return [content for content in self.content if isinstance(content, content_type)] + + def is_text(self) -> bool: + return all(isinstance(content, TextMessageContent) for content in self.content) + def to_text(self) -> str: return "".join( [content.artifact.to_text() for content in self.content if isinstance(content, TextMessageContent)] diff --git a/griptape/common/prompt_stack/prompt_stack.py b/griptape/common/prompt_stack/prompt_stack.py index ce19696e3..8bbe98161 100644 --- a/griptape/common/prompt_stack/prompt_stack.py +++ b/griptape/common/prompt_stack/prompt_stack.py @@ -1,14 +1,28 @@ from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact, ImageArtifact +from griptape.artifacts import ActionArtifact, BaseArtifact, ImageArtifact, ListArtifact, TextArtifact +from griptape.common import ( + ActionCallMessageContent, + ActionResultMessageContent, + BaseMessageContent, + ImageMessageContent, + Message, + TextMessageContent, +) from griptape.mixins import SerializableMixin -from griptape.common import Message, TextMessageContent, BaseMessageContent, ImageMessageContent + +if TYPE_CHECKING: + from griptape.tools import BaseTool @define class PromptStack(SerializableMixin): messages: list[Message] = field(factory=list, kw_only=True, metadata={"serializable": True}) + tools: list[BaseTool] = field(factory=list, kw_only=True) @property def system_messages(self) -> list[Message]: @@ -23,9 +37,9 @@ def assistant_messages(self) -> list[Message]: return [message for message in self.messages if message.is_assistant()] def add_message(self, artifact: str | BaseArtifact, role: str) -> Message: - new_content = self.__process_artifact(artifact) + content = self.__to_message_content(artifact) - self.messages.append(Message(content=new_content, role=role)) + self.messages.append(Message(content=content, role=role)) return self.messages[-1] @@ -38,15 +52,22 @@ def add_user_message(self, artifact: str | BaseArtifact) -> Message: def add_assistant_message(self, artifact: str | BaseArtifact) -> Message: return self.add_message(artifact, Message.ASSISTANT_ROLE) - def __process_artifact(self, artifact: str | BaseArtifact) -> list[BaseMessageContent]: + def __to_message_content(self, artifact: str | BaseArtifact) -> list[BaseMessageContent]: if isinstance(artifact, str): return [TextMessageContent(TextArtifact(artifact))] elif isinstance(artifact, TextArtifact): return [TextMessageContent(artifact)] elif isinstance(artifact, ImageArtifact): return [ImageMessageContent(artifact)] + elif isinstance(artifact, ActionArtifact): + action = artifact.value + output = action.output + if output is None: + return [ActionCallMessageContent(artifact)] + else: + return [ActionResultMessageContent(output, action=action)] elif isinstance(artifact, ListArtifact): - processed_contents = [self.__process_artifact(artifact) for artifact in artifact.value] + processed_contents = [self.__to_message_content(artifact) for artifact in artifact.value] flattened_content = [ sub_content for processed_content in processed_contents for sub_content in processed_content ] diff --git a/griptape/config/anthropic_structure_config.py b/griptape/config/anthropic_structure_config.py index 28bb5f657..58db8d476 100644 --- a/griptape/config/anthropic_structure_config.py +++ b/griptape/config/anthropic_structure_config.py @@ -33,7 +33,7 @@ class AnthropicStructureConfig(StructureConfig): metadata={"serializable": True}, ) image_query_driver: BaseImageQueryDriver = field( - default=Factory(lambda: AnthropicImageQueryDriver(model="claude-3-opus-20240229")), + default=Factory(lambda: AnthropicImageQueryDriver(model="claude-3-5-sonnet-20240620")), kw_only=True, metadata={"serializable": True}, ) diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 21d81724d..8a1072716 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -4,15 +4,29 @@ from typing import TYPE_CHECKING, Any from attrs import Factory, define, field - -from griptape.artifacts import TextArtifact +from schema import Schema + +from griptape.artifacts import ( + ActionArtifact, + BaseArtifact, + ErrorArtifact, + ImageArtifact, + InfoArtifact, + ListArtifact, + TextArtifact, +) from griptape.common import ( + ActionCallDeltaMessageContent, + ActionCallMessageContent, + ActionResultMessageContent, + BaseDeltaMessageContent, + BaseMessageContent, DeltaMessage, + ImageMessageContent, Message, TextDeltaMessageContent, - BaseMessageContent, TextMessageContent, - ImageMessageContent, + ToolAction, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AmazonBedrockTokenizer, BaseTokenizer @@ -22,6 +36,7 @@ import boto3 from griptape.common import PromptStack + from griptape.tools import BaseTool @define @@ -34,6 +49,8 @@ class AmazonBedrockPromptDriver(BasePromptDriver): tokenizer: BaseTokenizer = field( default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True ) + use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) + tool_choice: dict = field(default=Factory(lambda: {"auto": {}}), kw_only=True, metadata={"serializable": True}) def try_run(self, prompt_stack: PromptStack) -> Message: response = self.bedrock_client.converse(**self._base_params(prompt_stack)) @@ -42,7 +59,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: output_message = response["output"]["message"] return Message( - content=[TextMessageContent(TextArtifact(content["text"])) for content in output_message["content"]], + content=[self.__to_prompt_stack_message_content(content) for content in output_message["content"]], role=Message.ASSISTANT_ROLE, usage=Message.Usage(input_tokens=usage["inputTokens"], output_tokens=usage["outputTokens"]), ) @@ -53,13 +70,8 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: stream = response.get("stream") if stream is not None: for event in stream: - if "contentBlockDelta" in event: - content_block_delta = event["contentBlockDelta"] - yield DeltaMessage( - content=TextDeltaMessageContent( - content_block_delta["delta"]["text"], index=content_block_delta["contentBlockIndex"] - ) - ) + if "contentBlockDelta" in event or "contentBlockStart" in event: + yield DeltaMessage(content=self.__to_prompt_stack_delta_message_content(event)) elif "metadata" in event: usage = event["metadata"]["usage"] yield DeltaMessage( @@ -68,21 +80,10 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: else: raise Exception("model response is empty") - def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: - return [ - { - "role": self.__to_role(message), - "content": [self.__prompt_stack_content_message_content(content) for content in message.content], - } - for message in messages - ] - def _base_params(self, prompt_stack: PromptStack) -> dict: system_messages = [{"text": message.to_text()} for message in prompt_stack.system_messages] - messages = self._prompt_stack_messages_to_messages( - [message for message in prompt_stack.messages if not message.is_system()] - ) + messages = self.__to_bedrock_messages([message for message in prompt_stack.messages if not message.is_system()]) return { "modelId": self.model, @@ -90,18 +91,135 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "system": system_messages, "inferenceConfig": {"temperature": self.temperature}, "additionalModelRequestFields": self.additional_model_request_fields, + **( + {"toolConfig": {"tools": self.__to_bedrock_tools(prompt_stack.tools), "toolChoice": self.tool_choice}} + if prompt_stack.tools and self.use_native_tools + else {} + ), } - def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + def __to_bedrock_messages(self, messages: list[Message]) -> list[dict]: + return [ + { + "role": self.__to_bedrock_role(message), + "content": [self.__to_bedrock_message_content(content) for content in message.content], + } + for message in messages + ] + + def __to_bedrock_role(self, message: Message) -> str: + if message.is_assistant(): + return "assistant" + else: + return "user" + + def __to_bedrock_tools(self, tools: list[BaseTool]) -> list[dict]: + return [ + { + "toolSpec": { + "name": f"{tool.name}_{tool.activity_name(activity)}", + "description": tool.activity_description(activity), + "inputSchema": { + "json": (tool.activity_schema(activity) or Schema({})).json_schema( + "http://json-schema.org/draft-07/schema#" + ) + }, + } + } + for tool in tools + for activity in tool.activities() + ] + + def __to_bedrock_message_content(self, content: BaseMessageContent) -> dict: if isinstance(content, TextMessageContent): return {"text": content.artifact.to_text()} elif isinstance(content, ImageMessageContent): - return {"image": {"format": content.artifact.format, "source": {"bytes": content.artifact.value}}} + artifact = content.artifact + + return {"image": {"format": artifact.format, "source": {"bytes": artifact.value}}} + elif isinstance(content, ActionCallMessageContent): + action_call = content.artifact.value + + return { + "toolUse": { + "toolUseId": action_call.tag, + "name": f"{action_call.name}_{action_call.path}", + "input": action_call.input, + } + } + elif isinstance(content, ActionResultMessageContent): + artifact = content.artifact + + if isinstance(artifact, ListArtifact): + message_content = [self.__to_bedrock_tool_use_content(artifact) for artifact in artifact.value] + else: + message_content = [self.__to_bedrock_tool_use_content(artifact)] + + return { + "toolResult": { + "toolUseId": content.action.tag, + "content": message_content, + "status": "error" if isinstance(artifact, ErrorArtifact) else "success", + } + } else: raise ValueError(f"Unsupported content type: {type(content)}") - def __to_role(self, message: Message) -> str: - if message.is_assistant(): - return "assistant" + def __to_bedrock_tool_use_content(self, artifact: BaseArtifact) -> dict: + if isinstance(artifact, ImageArtifact): + return {"image": {"format": artifact.format, "source": {"bytes": artifact.value}}} + elif isinstance(artifact, (TextArtifact, ErrorArtifact, InfoArtifact)): + return {"text": artifact.to_text()} else: - return "user" + raise ValueError(f"Unsupported artifact type: {type(artifact)}") + + def __to_prompt_stack_message_content(self, content: dict) -> BaseMessageContent: + if "text" in content: + return TextMessageContent(TextArtifact(content["text"])) + elif "toolUse" in content: + name, path = ToolAction.from_native_tool_name(content["toolUse"]["name"]) + return ActionCallMessageContent( + artifact=ActionArtifact( + value=ToolAction( + tag=content["toolUse"]["toolUseId"], name=name, path=path, input=content["toolUse"]["input"] + ) + ) + ) + else: + raise ValueError(f"Unsupported message content type: {content}") + + def __to_prompt_stack_delta_message_content(self, event: dict) -> BaseDeltaMessageContent: + if "contentBlockStart" in event: + content_block = event["contentBlockStart"]["start"] + + if "toolUse" in content_block: + name, path = ToolAction.from_native_tool_name(content_block["toolUse"]["name"]) + + return ActionCallDeltaMessageContent( + index=event["contentBlockStart"]["contentBlockIndex"], + tag=content_block["toolUse"]["toolUseId"], + name=name, + path=path, + ) + elif "text" in content_block: + return TextDeltaMessageContent( + content_block["text"], index=event["contentBlockStart"]["contentBlockIndex"] + ) + else: + raise ValueError(f"Unsupported message content type: {event}") + elif "contentBlockDelta" in event: + content_block_delta = event["contentBlockDelta"] + + if "text" in content_block_delta["delta"]: + return TextDeltaMessageContent( + content_block_delta["delta"]["text"], index=content_block_delta["contentBlockIndex"] + ) + elif "toolUse" in content_block_delta["delta"]: + return ActionCallDeltaMessageContent( + index=content_block_delta["contentBlockIndex"], + partial_input=content_block_delta["delta"]["toolUse"]["input"], + ) + else: + raise ValueError(f"Unsupported message content type: {event}") + else: + raise ValueError(f"Unsupported message content type: {event}") diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 2c338c84c..21fdc841c 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -1,18 +1,32 @@ from __future__ import annotations from collections.abc import Iterator -from typing import Any, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from attrs import Factory, define, field - -from griptape.artifacts import TextArtifact +from schema import Schema + +from griptape.artifacts import ( + ActionArtifact, + BaseArtifact, + ErrorArtifact, + ImageArtifact, + InfoArtifact, + ListArtifact, + TextArtifact, +) from griptape.common import ( + ActionCallMessageContent, + ActionResultMessageContent, + BaseDeltaMessageContent, BaseMessageContent, + ActionCallDeltaMessageContent, DeltaMessage, TextDeltaMessageContent, ImageMessageContent, PromptStack, Message, + ToolAction, TextMessageContent, ) from griptape.drivers import BasePromptDriver @@ -20,8 +34,10 @@ from griptape.utils import import_optional_dependency if TYPE_CHECKING: - from anthropic.types import ContentBlockDeltaEvent - from anthropic.types import ContentBlock + from anthropic import Client + from anthropic.types import ContentBlock, ContentBlockDeltaEvent, ContentBlockStartEvent + + from griptape.tools.base_tool import BaseTool @define @@ -35,7 +51,7 @@ class AnthropicPromptDriver(BasePromptDriver): api_key: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) model: str = field(kw_only=True, metadata={"serializable": True}) - client: Any = field( + client: Client = field( default=Factory( lambda self: import_optional_dependency("anthropic").Anthropic(api_key=self.api_key), takes_self=True ), @@ -46,13 +62,15 @@ class AnthropicPromptDriver(BasePromptDriver): ) top_p: float = field(default=0.999, kw_only=True, metadata={"serializable": True}) top_k: int = field(default=250, kw_only=True, metadata={"serializable": True}) + tool_choice: dict = field(default=Factory(lambda: {"type": "auto"}), kw_only=True, metadata={"serializable": False}) + use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) max_tokens: int = field(default=1000, kw_only=True, metadata={"serializable": True}) def try_run(self, prompt_stack: PromptStack) -> Message: response = self.client.messages.create(**self._base_params(prompt_stack)) return Message( - content=[self.__message_content_to_prompt_stack_content(content) for content in response.content], + content=[self.__to_prompt_stack_message_content(content) for content in response.content], role=Message.ASSISTANT_ROLE, usage=Message.Usage(input_tokens=response.usage.input_tokens, output_tokens=response.usage.output_tokens), ) @@ -61,20 +79,15 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: events = self.client.messages.create(**self._base_params(prompt_stack), stream=True) for event in events: - if event.type == "content_block_delta": - yield DeltaMessage(content=self.__message_content_delta_to_prompt_stack_content_delta(event)) + if event.type == "content_block_delta" or event.type == "content_block_start": + yield DeltaMessage(content=self.__to_prompt_stack_delta_message_content(event)) elif event.type == "message_start": yield DeltaMessage(usage=DeltaMessage.Usage(input_tokens=event.message.usage.input_tokens)) elif event.type == "message_delta": yield DeltaMessage(usage=DeltaMessage.Usage(output_tokens=event.usage.output_tokens)) - def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: - return [{"role": self.__to_role(message), "content": self.__to_content(message)} for message in messages] - def _base_params(self, prompt_stack: PromptStack) -> dict: - messages = self._prompt_stack_messages_to_messages( - [message for message in prompt_stack.messages if not message.is_system()] - ) + messages = self.__to_anthropic_messages([i for i in prompt_stack.messages if not i.is_system()]) system_messages = prompt_stack.system_messages system_message = system_messages[0].to_text() if system_messages else None @@ -87,44 +100,121 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "top_k": self.top_k, "max_tokens": self.max_tokens, "messages": messages, + **( + {"tools": self.__to_anthropic_tools(prompt_stack.tools), "tool_choice": self.tool_choice} + if prompt_stack.tools and self.use_native_tools + else {} + ), **({"system": system_message} if system_message else {}), } - def __to_role(self, message: Message) -> str: + def __to_anthropic_messages(self, messages: list[Message]) -> list[dict]: + return [ + {"role": self.__to_anthropic_role(message), "content": self.__to_anthropic_content(message)} + for message in messages + ] + + def __to_anthropic_role(self, message: Message) -> str: if message.is_assistant(): return "assistant" else: return "user" - def __to_content(self, message: Message) -> str | list[dict]: - if all(isinstance(content, TextMessageContent) for content in message.content): + def __to_anthropic_tools(self, tools: list[BaseTool]) -> list[dict]: + return [ + { + "name": f"{tool.name}_{tool.activity_name(activity)}", + "description": tool.activity_description(activity), + "input_schema": (tool.activity_schema(activity) or Schema({})).json_schema("Input Schema"), + } + for tool in tools + for activity in tool.activities() + ] + + def __to_anthropic_content(self, message: Message) -> str | list[dict]: + if message.has_all_content_type(TextMessageContent): return message.to_text() else: - return [self.__prompt_stack_content_message_content(content) for content in message.content] + return [self.__to_anthropic_message_content(content) for content in message.content] - def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + def __to_anthropic_message_content(self, content: BaseMessageContent) -> dict: if isinstance(content, TextMessageContent): - return {"type": "text", "text": content.artifact.to_text()} + return {"type": "text", "text": content.artifact.value} elif isinstance(content, ImageMessageContent): + artifact = content.artifact + return { "type": "image", - "source": {"type": "base64", "media_type": content.artifact.mime_type, "data": content.artifact.base64}, + "source": {"type": "base64", "media_type": artifact.mime_type, "data": artifact.base64}, + } + elif isinstance(content, ActionCallMessageContent): + action = content.artifact.value + + return {"type": "tool_use", "id": action.tag, "name": action.to_native_tool_name(), "input": action.input} + elif isinstance(content, ActionResultMessageContent): + artifact = content.artifact + + if isinstance(artifact, ListArtifact): + message_content = [self.__to_anthropic_tool_result_content(artifact) for artifact in artifact.value] + else: + message_content = [self.__to_anthropic_tool_result_content(artifact)] + + return { + "type": "tool_result", + "tool_use_id": content.action.tag, + "content": message_content, + "is_error": isinstance(artifact, ErrorArtifact), } else: raise ValueError(f"Unsupported prompt content type: {type(content)}") - def __message_content_to_prompt_stack_content(self, content: ContentBlock) -> BaseMessageContent: + def __to_anthropic_tool_result_content(self, artifact: BaseArtifact) -> dict: + if isinstance(artifact, ImageArtifact): + return { + "type": "image", + "source": {"type": "base64", "media_type": artifact.mime_type, "data": artifact.base64}, + } + elif isinstance(artifact, (TextArtifact, ErrorArtifact, InfoArtifact)): + return {"type": "text", "text": artifact.to_text()} + else: + raise ValueError(f"Unsupported tool result artifact type: {type(artifact)}") + + def __to_prompt_stack_message_content(self, content: ContentBlock) -> BaseMessageContent: if content.type == "text": return TextMessageContent(TextArtifact(content.text)) + elif content.type == "tool_use": + name, path = ToolAction.from_native_tool_name(content.name) + + return ActionCallMessageContent( + artifact=ActionArtifact( + value=ToolAction(tag=content.id, name=name, path=path, input=content.input) # pyright: ignore[reportArgumentType] + ) + ) else: raise ValueError(f"Unsupported message content type: {content.type}") - def __message_content_delta_to_prompt_stack_content_delta( - self, content_delta: ContentBlockDeltaEvent - ) -> TextDeltaMessageContent: - index = content_delta.index - - if content_delta.delta.type == "text_delta": - return TextDeltaMessageContent(content_delta.delta.text, index=index) + def __to_prompt_stack_delta_message_content( + self, event: ContentBlockDeltaEvent | ContentBlockStartEvent + ) -> BaseDeltaMessageContent: + if event.type == "content_block_start": + content_block = event.content_block + + if content_block.type == "tool_use": + name, path = ToolAction.from_native_tool_name(content_block.name) + + return ActionCallDeltaMessageContent(index=event.index, tag=content_block.id, name=name, path=path) + elif content_block.type == "text": + return TextDeltaMessageContent(content_block.text, index=event.index) + else: + raise ValueError(f"Unsupported content block type: {content_block.type}") + elif event.type == "content_block_delta": + content_block_delta = event.delta + + if content_block_delta.type == "text_delta": + return TextDeltaMessageContent(content_block_delta.text, index=event.index) + elif content_block_delta.type == "input_json_delta": + return ActionCallDeltaMessageContent(index=event.index, partial_input=content_block_delta.partial_json) + else: + raise ValueError(f"Unsupported message content type: {event}") else: - raise ValueError(f"Unsupported message content delta type : {content_delta.delta.type}") + raise ValueError(f"Unsupported message content type: {event}") diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index b499179ed..ea785d045 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -7,7 +7,9 @@ from attrs import Factory, define, field from griptape.common import ( + ActionCallMessageContent, BaseDeltaMessageContent, + ActionCallDeltaMessageContent, DeltaMessage, TextDeltaMessageContent, PromptStack, @@ -35,6 +37,7 @@ class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): model: The model name. tokenizer: An instance of `BaseTokenizer` to when calculating tokens. stream: Whether to stream the completion or not. `CompletionChunkEvent`s will be published to the `Structure` if one is provided. + use_native_tools: Whether to use LLM's native function calling capabilities. Must be supported by the model. """ temperature: float = field(default=0.1, metadata={"serializable": True}) @@ -43,7 +46,8 @@ class BasePromptDriver(SerializableMixin, ExponentialBackoffMixin, ABC): ignored_exception_types: tuple[type[Exception], ...] = field(default=Factory(lambda: (ImportError, ValueError))) model: str = field(metadata={"serializable": True}) tokenizer: BaseTokenizer - stream: bool = field(default=False, metadata={"serializable": True}) + stream: bool = field(default=False, kw_only=True, metadata={"serializable": True}) + use_native_tools: bool = field(default=False, kw_only=True, metadata={"serializable": True}) def before_run(self, prompt_stack: PromptStack) -> None: if self.structure: @@ -114,25 +118,34 @@ def __process_stream(self, prompt_stack: PromptStack) -> Message: usage = DeltaMessage.Usage() # Aggregate all content deltas from the stream - deltas = self.try_stream(prompt_stack) - for delta in deltas: - usage += delta.usage - - if delta.content is not None: - if delta.content.index in delta_contents: - delta_contents[delta.content.index].append(delta.content) + message_deltas = self.try_stream(prompt_stack) + for message_delta in message_deltas: + usage += message_delta.usage + content = message_delta.content + + if content is not None: + if content.index in delta_contents: + delta_contents[content.index].append(content) else: - delta_contents[delta.content.index] = [delta.content] - - if isinstance(delta.content, TextDeltaMessageContent): - self.structure.publish_event(CompletionChunkEvent(token=delta.content.text)) + delta_contents[content.index] = [content] + if isinstance(content, TextDeltaMessageContent): + self.structure.publish_event(CompletionChunkEvent(token=content.text)) + elif isinstance(content, ActionCallDeltaMessageContent): + if content.tag is not None and content.name is not None and content.path is not None: + self.structure.publish_event(CompletionChunkEvent(token=str(content))) + elif content.partial_input is not None: + self.structure.publish_event(CompletionChunkEvent(token=content.partial_input)) # Build a complete content from the content deltas content = [] - for deltas in delta_contents.values(): - text_deltas = [delta for delta in deltas if isinstance(delta, TextDeltaMessageContent)] + for delta_content in delta_contents.values(): + text_deltas = [delta for delta in delta_content if isinstance(delta, TextDeltaMessageContent)] + action_deltas = [delta for delta in delta_content if isinstance(delta, ActionCallDeltaMessageContent)] + if text_deltas: content.append(TextMessageContent.from_deltas(text_deltas)) + if action_deltas: + content.append(ActionCallMessageContent.from_deltas(action_deltas)) result = Message( content=content, diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index b00abd855..a07489005 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -1,23 +1,32 @@ from __future__ import annotations -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any from collections.abc import Iterator from attrs import define, field, Factory from griptape.artifacts import TextArtifact +from griptape.artifacts.list_artifact import ListArtifact +from griptape.common.prompt_stack.contents.action_call_delta_message_content import ActionCallDeltaMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import CohereTokenizer +from griptape.artifacts import ActionArtifact from griptape.common import ( + ActionCallMessageContent, + BaseDeltaMessageContent, + BaseMessageContent, + DeltaMessage, + TextDeltaMessageContent, PromptStack, Message, - DeltaMessage, TextMessageContent, - BaseMessageContent, - TextDeltaMessageContent, + ActionResultMessageContent, + ToolAction, ) from griptape.utils import import_optional_dependency from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: from cohere import Client + from cohere.types import NonStreamedChatResponse + from griptape.tools import BaseTool @define(kw_only=True) @@ -37,13 +46,15 @@ class CoherePromptDriver(BasePromptDriver): tokenizer: BaseTokenizer = field( default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True) ) + force_single_step: bool = field(default=False, kw_only=True, metadata={"serializable": True}) + use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) def try_run(self, prompt_stack: PromptStack) -> Message: result = self.client.chat(**self._base_params(prompt_stack)) usage = result.meta.tokens return Message( - content=[TextMessageContent(TextArtifact(result.text))], + content=self.__to_prompt_stack_message_content(result), role=Message.ASSISTANT_ROLE, usage=Message.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens), ) @@ -52,32 +63,34 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: result = self.client.chat_stream(**self._base_params(prompt_stack)) for event in result: - if event.event_type == "text-generation": - yield DeltaMessage(content=TextDeltaMessageContent(event.text, index=0)) - elif event.event_type == "stream-end": + if event.event_type == "stream-end": usage = event.response.meta.tokens yield DeltaMessage( usage=DeltaMessage.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens) ) - - def _prompt_stack_messages_to_messages(self, messages: list[Message]) -> list[dict]: - return [ - { - "role": self.__to_role(message), - "content": [self.__prompt_stack_content_message_content(content) for content in message.content], - } - for message in messages - ] + elif event.event_type == "text-generation" or event.event_type == "tool-calls-chunk": + yield DeltaMessage(content=self.__to_prompt_stack_delta_message_content(event)) def _base_params(self, prompt_stack: PromptStack) -> dict: + # Current message last_input = prompt_stack.messages[-1] - user_message = last_input.to_text() - - history_messages = self._prompt_stack_messages_to_messages( + user_message = "" + tool_results = [] + if last_input is not None: + message = self.__to_cohere_messages([prompt_stack.messages[-1]]) + + if "message" in message[0]: + user_message = message[0]["message"] + if "tool_results" in message[0]: + tool_results = message[0]["tool_results"] + + # History messages + history_messages = self.__to_cohere_messages( [message for message in prompt_stack.messages[:-1] if not message.is_system()] ) + # System message (preamble) system_messages = prompt_stack.system_messages preamble = system_messages[0].to_text() if system_messages else None @@ -87,19 +100,142 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "temperature": self.temperature, "stop_sequences": self.tokenizer.stop_sequences, "max_tokens": self.max_tokens, + **({"tool_results": tool_results} if tool_results else {}), + **( + {"tools": self.__to_cohere_tools(prompt_stack.tools), "force_single_step": self.force_single_step} + if prompt_stack.tools and self.use_native_tools + else {} + ), **({"preamble": preamble} if preamble else {}), } - def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: - if isinstance(content, TextMessageContent): + def __to_cohere_messages(self, messages: list[Message]) -> list[dict]: + cohere_messages = [] + + for message in messages: + cohere_message: dict = {"role": self.__to_cohere_role(message), "message": message.to_text()} + + if message.has_any_content_type(ActionResultMessageContent): + cohere_message["tool_results"] = [ + self.__to_cohere_message_content(action_result) + for action_result in message.get_content_type(ActionResultMessageContent) + ] + else: + if message.has_any_content_type(ActionCallMessageContent): + cohere_message["tool_calls"] = [ + self.__to_cohere_message_content(action_call) + for action_call in message.get_content_type(ActionCallMessageContent) + ] + + cohere_messages.append(cohere_message) + + return cohere_messages + + def __to_cohere_message_content(self, content: BaseMessageContent) -> str | dict: + if isinstance(content, ActionCallMessageContent): + action = content.artifact.value + + return {"name": action.to_native_tool_name(), "parameters": action.input} + elif isinstance(content, ActionResultMessageContent): + artifact = content.artifact + + if isinstance(artifact, ListArtifact): + message_content = [{"text": artifact.to_text()} for artifact in artifact.value] + else: + message_content = [{"text": artifact.to_text()}] + + return { + "call": {"name": content.action.to_native_tool_name(), "parameters": content.action.input}, + "outputs": message_content, + } + elif isinstance(content, ActionResultMessageContent): return {"text": content.artifact.to_text()} else: raise ValueError(f"Unsupported content type: {type(content)}") - def __to_role(self, message: Message) -> str: + def __to_cohere_role(self, message: Message) -> str: if message.is_system(): return "SYSTEM" - elif message.is_user(): - return "USER" - else: + elif message.is_assistant(): return "CHATBOT" + else: + if message.has_any_content_type(ActionResultMessageContent): + return "TOOL" + else: + return "USER" + + def __to_cohere_tools(self, tools: list[BaseTool]) -> list[dict]: + tool_definitions = [] + + for tool in tools: + for activity in tool.activities(): + activity_schema = tool.activity_schema(activity) + if activity_schema is not None: + properties_values = activity_schema.json_schema("Parameters Schema")["properties"]["values"] + + properties = properties_values["properties"] + else: + properties_values = {} + properties = {} + + tool_definitions.append( + { + "name": f"{tool.name}_{tool.activity_name(activity)}", + "description": tool.activity_description(activity), + "parameter_definitions": { + property_name: { + "type": property_value["type"], + "required": property_name in properties_values["required"], + **( + {"description": property_value["description"]} + if "description" in property_value + else {} + ), + } + for property_name, property_value in properties.items() + }, + } + ) + + return tool_definitions + + def __to_prompt_stack_message_content(self, response: NonStreamedChatResponse) -> list[BaseMessageContent]: + content = [] + if response.text: + content.append(TextMessageContent(TextArtifact(response.text))) + if response.tool_calls is not None: + content.extend( + [ + ActionCallMessageContent( + ActionArtifact( + ToolAction( + tag=tool_call.name, + name=ToolAction.from_native_tool_name(tool_call.name)[0], + path=ToolAction.from_native_tool_name(tool_call.name)[1], + input=tool_call.parameters, + ) + ) + ) + for tool_call in response.tool_calls + ] + ) + + return content + + def __to_prompt_stack_delta_message_content(self, event: Any) -> BaseDeltaMessageContent: + if event.event_type == "text-generation": + return TextDeltaMessageContent(event.text, index=0) + elif event.event_type == "tool-calls-chunk": + if event.tool_call_delta is not None: + tool_call_delta = event.tool_call_delta + if tool_call_delta.name is not None: + name, path = ToolAction.from_native_tool_name(tool_call_delta.name) + + return ActionCallDeltaMessageContent(tag=tool_call_delta.name, name=name, path=path) + else: + return ActionCallDeltaMessageContent(partial_input=tool_call_delta.parameters) + + else: + return TextDeltaMessageContent(event.text) + else: + raise ValueError(f"Unsupported event type: {event.event_type}") diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index ff4b07a93..41be786b6 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -1,11 +1,13 @@ from __future__ import annotations +import json from collections.abc import Iterator -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Optional from attrs import Factory, define, field +from google.generativeai.types import ContentsType + -from griptape.artifacts import TextArtifact from griptape.common import ( BaseMessageContent, DeltaMessage, @@ -14,14 +16,23 @@ PromptStack, Message, TextMessageContent, + ActionCallMessageContent, + ActionResultMessageContent, + ActionCallDeltaMessageContent, + BaseDeltaMessageContent, + ToolAction, ) +from griptape.artifacts import TextArtifact, ActionArtifact from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer, GoogleTokenizer -from griptape.utils import import_optional_dependency +from griptape.utils import import_optional_dependency, remove_key_in_dict_recursively +from schema import Schema if TYPE_CHECKING: from google.generativeai import GenerativeModel from google.generativeai.types import ContentDict, GenerateContentResponse + from google.generativeai.protos import Part + from griptape.tools import BaseTool @define @@ -37,33 +48,28 @@ class GooglePromptDriver(BasePromptDriver): api_key: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) model: str = field(kw_only=True, metadata={"serializable": True}) - model_client: Any = field(default=Factory(lambda self: self._default_model_client(), takes_self=True), kw_only=True) + model_client: GenerativeModel = field( + default=Factory(lambda self: self._default_model_client(), takes_self=True), kw_only=True + ) tokenizer: BaseTokenizer = field( default=Factory(lambda self: GoogleTokenizer(api_key=self.api_key, model=self.model), takes_self=True), kw_only=True, ) top_p: Optional[float] = field(default=None, kw_only=True, metadata={"serializable": True}) top_k: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) + use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) + tool_choice: str = field(default="auto", kw_only=True, metadata={"serializable": True}) def try_run(self, prompt_stack: PromptStack) -> Message: - GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig - - messages = self._prompt_stack_to_messages(prompt_stack) + messages = self.__to_google_messages(prompt_stack) response: GenerateContentResponse = self.model_client.generate_content( - messages, - generation_config=GenerationConfig( - stop_sequences=self.tokenizer.stop_sequences, - max_output_tokens=self.max_tokens, - temperature=self.temperature, - top_p=self.top_p, - top_k=self.top_k, - ), + messages, **self._base_params(prompt_stack) ) usage_metadata = response.usage_metadata return Message( - content=[TextMessageContent(TextArtifact(response.text))], + content=[self.__to_prompt_stack_message_content(part) for part in response.parts], role=Message.ASSISTANT_ROLE, usage=Message.Usage( input_tokens=usage_metadata.prompt_token_count, output_tokens=usage_metadata.candidates_token_count @@ -71,31 +77,21 @@ def try_run(self, prompt_stack: PromptStack) -> Message: ) def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: - GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig - - messages = self._prompt_stack_to_messages(prompt_stack) - response: Iterator[GenerateContentResponse] = self.model_client.generate_content( - messages, - stream=True, - generation_config=GenerationConfig( - stop_sequences=self.tokenizer.stop_sequences, - max_output_tokens=self.max_tokens, - temperature=self.temperature, - top_p=self.top_p, - top_k=self.top_k, - ), + messages = self.__to_google_messages(prompt_stack) + response: GenerateContentResponse = self.model_client.generate_content( + messages, **self._base_params(prompt_stack), stream=True ) prompt_token_count = None for chunk in response: usage_metadata = chunk.usage_metadata + content = self.__to_prompt_stack_delta_message_content(chunk.parts[0]) if chunk.parts else None # Only want to output the prompt token count once since it is static each chunk if prompt_token_count is None: prompt_token_count = usage_metadata.prompt_token_count yield DeltaMessage( - content=TextDeltaMessageContent(chunk.text), - role=Message.ASSISTANT_ROLE, + content=content, usage=DeltaMessage.Usage( input_tokens=usage_metadata.prompt_token_count, output_tokens=usage_metadata.candidates_token_count, @@ -103,46 +99,146 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: ) else: yield DeltaMessage( - content=TextDeltaMessageContent(chunk.text), - role=Message.ASSISTANT_ROLE, - usage=DeltaMessage.Usage(output_tokens=usage_metadata.candidates_token_count), + content=content, usage=DeltaMessage.Usage(output_tokens=usage_metadata.candidates_token_count) ) + def _base_params(self, prompt_stack: PromptStack) -> dict: + GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig + ContentDict = import_optional_dependency("google.generativeai.types").ContentDict + Part = import_optional_dependency("google.generativeai.protos").Part + + system_messages = prompt_stack.system_messages + if system_messages: + self.model_client._system_instruction = ContentDict( + role="system", parts=[Part(text=system_message.to_text()) for system_message in system_messages] + ) + + return { + "generation_config": GenerationConfig( + **{ + # For some reason, providing stop sequences when streaming breaks native functions + # https://github.com/google-gemini/generative-ai-python/issues/446 + "stop_sequences": [] if self.stream and self.use_native_tools else self.tokenizer.stop_sequences, + "max_output_tokens": self.max_tokens, + "temperature": self.temperature, + "top_p": self.top_p, + "top_k": self.top_k, + } + ), + **( + { + "tools": self.__to_google_tools(prompt_stack.tools), + "tool_config": {"function_calling_config": {"mode": self.tool_choice}}, + } + if prompt_stack.tools and self.use_native_tools + else {} + ), + } + def _default_model_client(self) -> GenerativeModel: genai = import_optional_dependency("google.generativeai") genai.configure(api_key=self.api_key) return genai.GenerativeModel(self.model) - def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: + def __to_google_messages(self, prompt_stack: PromptStack) -> ContentsType: + ContentDict = import_optional_dependency("google.generativeai.types").ContentDict + inputs = [ - {"role": self.__to_role(message), "parts": self.__to_content(message)} + ContentDict( + { + "role": self.__to_google_role(message), + "parts": [self.__to_google_message_content(content) for content in message.content], + } + ) for message in prompt_stack.messages if not message.is_system() ] - # Gemini does not have the notion of a system message, so we insert it as part of the first message in the history. - system_messages = prompt_stack.system_messages - if system_messages: - inputs[0]["parts"].insert(0, system_messages[0].to_text()) - return inputs - def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> ContentDict | str: + def __to_google_role(self, message: Message) -> str: + if message.is_assistant(): + return "model" + else: + return "user" + + def __to_google_tools(self, tools: list[BaseTool]) -> list[dict]: + FunctionDeclaration = import_optional_dependency("google.generativeai.types").FunctionDeclaration + + tool_declarations = [] + for tool in tools: + for activity in tool.activities(): + schema = (tool.activity_schema(activity) or Schema({})).json_schema("Parameters Schema") + + if "values" in schema["properties"]: + schema = schema["properties"]["values"] + + schema = remove_key_in_dict_recursively(schema, "additionalProperties") + tool_declaration = FunctionDeclaration( + name=f"{tool.name}_{tool.activity_name(activity)}", + description=tool.activity_description(activity), + parameters={ + "type": schema["type"], + "properties": schema["properties"], + "required": schema.get("required", []), + }, + ) + + tool_declarations.append(tool_declaration) + + return tool_declarations + + def __to_google_message_content(self, content: BaseMessageContent) -> ContentDict | Part | str: ContentDict = import_optional_dependency("google.generativeai.types").ContentDict + protos = import_optional_dependency("google.generativeai.protos") if isinstance(content, TextMessageContent): return content.artifact.to_text() elif isinstance(content, ImageMessageContent): return ContentDict(mime_type=content.artifact.mime_type, data=content.artifact.value) + elif isinstance(content, ActionCallMessageContent): + action = content.artifact.value + + return protos.Part(function_call=protos.FunctionCall(name=action.tag, args=action.input)) + elif isinstance(content, ActionResultMessageContent): + artifact = content.artifact + + return protos.Part( + function_response=protos.FunctionResponse( + name=content.action.to_native_tool_name(), response=artifact.to_dict() + ) + ) + else: - raise ValueError(f"Unsupported content type: {type(content)}") + raise ValueError(f"Unsupported prompt stack content type: {type(content)}") - def __to_role(self, message: Message) -> str: - if message.is_assistant(): - return "model" + def __to_prompt_stack_message_content(self, content: Part) -> BaseMessageContent: + if content.text: + return TextMessageContent(TextArtifact(content.text)) + elif content.function_call: + function_call = content.function_call + + name, path = ToolAction.from_native_tool_name(function_call.name) + + args = {k: v for k, v in function_call.args.items()} + return ActionCallMessageContent( + artifact=ActionArtifact(value=ToolAction(tag=function_call.name, name=name, path=path, input=args)) + ) else: - return "user" + raise ValueError(f"Unsupported message content type {content}") + + def __to_prompt_stack_delta_message_content(self, content: Part) -> BaseDeltaMessageContent: + if content.text: + return TextDeltaMessageContent(content.text) + elif content.function_call: + function_call = content.function_call - def __to_content(self, message: Message) -> list[ContentDict | str]: - return [self.__prompt_stack_content_message_content(content) for content in message.content] + name, path = ToolAction.from_native_tool_name(function_call.name) + + args = {k: v for k, v in function_call.args.items()} + return ActionCallDeltaMessageContent( + tag=function_call.name, name=name, path=path, partial_input=json.dumps(args) + ) + else: + raise ValueError(f"Unsupported message content type {content}") diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index a89b4eb57..d1456007e 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -1,28 +1,36 @@ from __future__ import annotations +import json from collections.abc import Iterator -from typing import Literal, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Literal, Optional import openai from attrs import Factory, define, field +from schema import Schema -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, ActionArtifact from griptape.common import ( + ActionCallMessageContent, + ActionResultMessageContent, + BaseDeltaMessageContent, BaseMessageContent, + ActionCallDeltaMessageContent, DeltaMessage, TextDeltaMessageContent, ImageMessageContent, PromptStack, Message, TextMessageContent, + ToolAction, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer - if TYPE_CHECKING: - from openai.types.chat.chat_completion_message import ChatCompletionMessage from openai.types.chat.chat_completion_chunk import ChoiceDelta + from openai.types.chat.chat_completion_message import ChatCompletionMessage + + from griptape.tools import BaseTool @define @@ -59,6 +67,8 @@ class OpenAiChatPromptDriver(BasePromptDriver): default=None, kw_only=True, metadata={"serializable": True} ) seed: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) + tool_choice: str = field(default="auto", kw_only=True, metadata={"serializable": False}) + use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) ignored_exception_types: tuple[type[Exception], ...] = field( default=Factory( lambda: ( @@ -80,8 +90,8 @@ def try_run(self, prompt_stack: PromptStack) -> Message: message = result.choices[0].message return Message( - content=[self.__message_to_prompt_stack_content(message)], - role=message.role, + content=self.__to_prompt_stack_message_content(message), + role=Message.ASSISTANT_ROLE, usage=Message.Usage( input_tokens=result.usage.prompt_tokens, output_tokens=result.usage.completion_tokens ), @@ -104,22 +114,21 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: choice = chunk.choices[0] delta = choice.delta - yield DeltaMessage(content=self.__message_delta_to_prompt_stack_content_delta(delta)) + yield DeltaMessage(content=self.__to_prompt_stack_delta_message_content(delta)) else: raise Exception("Completion with more than one choice is not supported yet.") - def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: - return [ - {"role": self.__to_role(message), "content": self.__to_content(message)} - for message in prompt_stack.messages - ] - def _base_params(self, prompt_stack: PromptStack) -> dict: params = { "model": self.model, "temperature": self.temperature, "user": self.user, "seed": self.seed, + **( + {"tools": self.__to_openai_tools(prompt_stack.tools), "tool_choice": self.tool_choice} + if prompt_stack.tools and self.use_native_tools + else {} + ), **({"stop": self.tokenizer.stop_sequences} if self.tokenizer.stop_sequences else {}), **({"max_tokens": self.max_tokens} if self.max_tokens is not None else {}), **({"stream_options": {"include_usage": True}} if self.stream else {}), @@ -130,27 +139,87 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: # JSON mode still requires a system message instructing the LLM to output JSON. prompt_stack.add_system_message("Provide your response as a valid JSON object.") - messages = self._prompt_stack_to_messages(prompt_stack) + messages = self.__to_openai_messages(prompt_stack.messages) params["messages"] = messages return params - def __to_role(self, message: Message) -> str: + def __to_openai_messages(self, messages: list[Message]) -> list[dict]: + openai_messages = [] + + for message in messages: + if message.is_text(): + openai_messages.append({"role": message.role, "content": message.to_text()}) + elif message.has_any_content_type(ActionResultMessageContent): + # ToolAction results need to be expanded into separate messages. + openai_messages.extend( + [ + { + "role": self.__to_openai_role(message), + "content": self.__to_openai_message_content(action_result), + "tool_call_id": action_result.action.tag, + } + for action_result in message.get_content_type(ActionResultMessageContent) + ] + ) + else: + # ToolAction calls are attached to the assistant message that originally generated them. + action_call_content = [] + non_action_call_content = [] + for content in message.content: + if isinstance(content, ActionCallMessageContent): + action_call_content.append(content) + else: + non_action_call_content.append(content) + + openai_messages.append( + { + "role": self.__to_openai_role(message), + "content": [ + self.__to_openai_message_content(content) + for content in non_action_call_content # ToolAction calls do not belong in the content + ], + **( + { + "tool_calls": [ + self.__to_openai_message_content(action_call) for action_call in action_call_content + ] + } + if action_call_content + else {} + ), + } + ) + + return openai_messages + + def __to_openai_role(self, message: Message) -> str: if message.is_system(): return "system" elif message.is_assistant(): return "assistant" else: - return "user" + if message.has_any_content_type(ActionResultMessageContent): + return "tool" + else: + return "user" - def __to_content(self, message: Message) -> str | list[dict]: - if all(isinstance(content, TextMessageContent) for content in message.content): - return message.to_text() - else: - return [self.__prompt_stack_content_message_content(content) for content in message.content] + def __to_openai_tools(self, tools: list[BaseTool]) -> list[dict]: + return [ + { + "function": { + "name": f"{tool.name}_{tool.activity_name(activity)}", + "description": tool.activity_description(activity), + "parameters": (tool.activity_schema(activity) or Schema({})).json_schema("Parameters Schema"), + }, + "type": "function", + } + for tool in tools + for activity in tool.activities() + ] - def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> dict: + def __to_openai_message_content(self, content: BaseMessageContent) -> str | dict: if isinstance(content, TextMessageContent): return {"type": "text", "text": content.artifact.to_text()} elif isinstance(content, ImageMessageContent): @@ -158,19 +227,64 @@ def __prompt_stack_content_message_content(self, content: BaseMessageContent) -> "type": "image_url", "image_url": {"url": f"data:{content.artifact.mime_type};base64,{content.artifact.base64}"}, } + elif isinstance(content, ActionCallMessageContent): + action = content.artifact.value + + return { + "type": "function", + "id": action.tag, + "function": {"name": action.to_native_tool_name(), "arguments": json.dumps(action.input)}, + } + elif isinstance(content, ActionResultMessageContent): + return content.artifact.to_text() else: raise ValueError(f"Unsupported content type: {type(content)}") - def __message_to_prompt_stack_content(self, message: ChatCompletionMessage) -> BaseMessageContent: - if message.content is not None: - return TextMessageContent(TextArtifact(message.content)) - else: - raise ValueError(f"Unsupported message type: {message}") + def __to_prompt_stack_message_content(self, response: ChatCompletionMessage) -> list[BaseMessageContent]: + content = [] - def __message_delta_to_prompt_stack_content_delta(self, content_delta: ChoiceDelta) -> TextDeltaMessageContent: - if content_delta.content is None: - return TextDeltaMessageContent("") - else: - delta_content = content_delta.content + if response.content is not None: + content.append(TextMessageContent(TextArtifact(response.content))) + if response.tool_calls is not None: + content.extend( + [ + ActionCallMessageContent( + ActionArtifact( + ToolAction( + tag=tool_call.id, + name=ToolAction.from_native_tool_name(tool_call.function.name)[0], + path=ToolAction.from_native_tool_name(tool_call.function.name)[1], + input=json.loads(tool_call.function.arguments), + ) + ) + ) + for tool_call in response.tool_calls + ] + ) + + return content + + def __to_prompt_stack_delta_message_content(self, content_delta: ChoiceDelta) -> BaseDeltaMessageContent: + if content_delta.content is not None: + return TextDeltaMessageContent(content_delta.content) + elif content_delta.tool_calls is not None: + tool_calls = content_delta.tool_calls + + if len(tool_calls) == 1: + tool_call = tool_calls[0] + index = tool_call.index - return TextDeltaMessageContent(delta_content) + # Tool call delta either contains the function header or the partial input. + if tool_call.id is not None and tool_call.function.name is not None: + return ActionCallDeltaMessageContent( + index=index, + tag=tool_call.id, + name=ToolAction.from_native_tool_name(tool_call.function.name)[0], + path=ToolAction.from_native_tool_name(tool_call.function.name)[1], + ) + else: + return ActionCallDeltaMessageContent(index=index, partial_input=tool_call.function.arguments) + else: + raise ValueError(f"Unsupported tool call delta length: {len(tool_calls)}") + else: + return TextDeltaMessageContent("") diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index e199a5c7e..867486700 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -105,25 +105,34 @@ def _resolve_types(cls, attrs_cls: type) -> None: # These modules are required to avoid `NameError`s when resolving types. from griptape.drivers import BaseConversationMemoryDriver, BasePromptDriver from griptape.structures import Structure - from griptape.common import PromptStack, Message, Reference + from griptape.common import PromptStack, Message, Reference, ToolAction from griptape.tokenizers.base_tokenizer import BaseTokenizer + from griptape.tools import BaseTool from typing import Any from griptape.artifacts import BaseArtifact boto3 = import_optional_dependency("boto3") if is_dependency_installed("boto3") else Any Client = import_optional_dependency("cohere").Client if is_dependency_installed("cohere") else Any + GenerativeModel = ( + import_optional_dependency("google.generativeai").GenerativeModel + if is_dependency_installed("google.generativeai") + else Any + ) attrs.resolve_types( attrs_cls, localns={ "PromptStack": PromptStack, "Usage": Message.Usage, + "BaseTool": BaseTool, "Structure": Structure, "BaseConversationMemoryDriver": BaseConversationMemoryDriver, "BasePromptDriver": BasePromptDriver, "BaseTokenizer": BaseTokenizer, "boto3": boto3, "Client": Client, + "ToolAction": ToolAction, + "GenerativeModel": GenerativeModel, "Reference": Reference, "BaseArtifact": BaseArtifact, }, diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index c835f2b84..da378f881 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -6,49 +6,39 @@ import schema from attrs import define, field from griptape import utils +from griptape.common import ToolAction from griptape.utils import remove_null_values_in_dict_recursively from griptape.mixins import ActionsSubtaskOriginMixin -from griptape.tasks import BaseTextInputTask, BaseTask -from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact, ListArtifact +from griptape.tasks import BaseTask +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact, ListArtifact, ActionArtifact from griptape.events import StartActionsSubtaskEvent, FinishActionsSubtaskEvent if TYPE_CHECKING: from griptape.memory import TaskMemory - from griptape.tools import BaseTool @define -class ActionsSubtask(BaseTextInputTask): - @define(kw_only=True) - class Action: - tag: str = field() - name: str = field() - path: Optional[str] = field(default=None) - input: dict = field() - tool: Optional[BaseTool] = field(default=None) - +class ActionsSubtask(BaseTask): THOUGHT_PATTERN = r"(?s)^Thought:\s*(.*?)$" ACTIONS_PATTERN = r"(?s)Actions:[^\[]*(\[.*\])" ANSWER_PATTERN = r"(?s)^Answer:\s?([\s\S]*)$" parent_task_id: Optional[str] = field(default=None, kw_only=True) thought: Optional[str] = field(default=None, kw_only=True) - actions: list[Action] = field(factory=list, kw_only=True) - - _input: Optional[str | TextArtifact | Callable[[BaseTask], TextArtifact]] = field(default=None) + actions: list[ToolAction] = field(factory=list, kw_only=True) + output: Optional[BaseArtifact] = field(default=None, init=False) + _input: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact] = field( + default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value=""), + alias="input", + ) _memory: Optional[TaskMemory] = None @property - def input(self) -> TextArtifact: - if isinstance(self._input, TextArtifact): - return self._input - elif isinstance(self._input, Callable): - return self._input(self) - else: - return TextArtifact(self._input) + def input(self) -> TextArtifact | ListArtifact: + return self._process_task_input(self._input) @input.setter - def input(self, value: str | TextArtifact | Callable[[BaseTask], TextArtifact]) -> None: + def input(self, value: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact]) -> None: self._input = value @property @@ -75,7 +65,16 @@ def children(self) -> list[BaseTask]: def attach_to(self, parent_task: BaseTask): self.parent_task_id = parent_task.id self.structure = parent_task.structure - self.__init_from_prompt(self.input.to_text()) + + try: + if isinstance(self.input, TextArtifact): + self.__init_from_prompt(self.input.to_text()) + else: + self.__init_from_artifacts(self.input) + except Exception as e: + self.structure.logger.error(f"Subtask {self.origin_task.id}\nError parsing tool action: {e}") + + self.output = ErrorArtifact(f"ToolAction input parsing error: {e}", exception=e) def before_run(self) -> None: self.structure.publish_event( @@ -90,12 +89,12 @@ def before_run(self) -> None: subtask_actions=self.actions_to_dicts(), ) ) - self.structure.logger.info(f"Subtask {self.id}\n{self.input.to_text()}") + self.structure.logger.info(f"Subtask {self.id}\n{self.actions_to_json()}") def run(self) -> BaseArtifact: try: - if any(a.name == "error" for a in self.actions): - errors = [a.input["error"] for a in self.actions if a.name == "error"] + if any(isinstance(a.output, ErrorArtifact) for a in self.actions): + errors = [a.output.value for a in self.actions if isinstance(a.output, ErrorArtifact)] self.output = ErrorArtifact("\n\n".join(errors)) else: @@ -117,13 +116,13 @@ def run(self) -> BaseArtifact: else: return ErrorArtifact("no tool output") - def execute_actions(self, actions: list[Action]) -> list[tuple[str, BaseArtifact]]: + def execute_actions(self, actions: list[ToolAction]) -> list[tuple[str, BaseArtifact]]: with self.futures_executor_fn() as executor: results = utils.execute_futures_dict({a.tag: executor.submit(self.execute_action, a) for a in actions}) return [r for r in results.values()] - def execute_action(self, action: Action) -> tuple[str, BaseArtifact]: + def execute_action(self, action: ToolAction) -> tuple[str, BaseArtifact]: if action.tool is not None: if action.path is not None: output = action.tool.execute(getattr(action.tool, action.path), self, action) @@ -131,6 +130,7 @@ def execute_action(self, action: Action) -> tuple[str, BaseArtifact]: output = ErrorArtifact("action path not found") else: output = ErrorArtifact("action name not found") + action.output = output return action.tag, output @@ -174,92 +174,114 @@ def actions_to_dicts(self) -> list[dict]: return json_list def actions_to_json(self) -> str: - return json.dumps(self.actions_to_dicts()) + return json.dumps(self.actions_to_dicts(), indent=2) + + def _process_task_input( + self, task_input: str | tuple | list | BaseArtifact | Callable[[BaseTask], BaseArtifact] + ) -> TextArtifact | ListArtifact: + if isinstance(task_input, (TextArtifact, ListArtifact)): + return task_input + elif isinstance(task_input, ActionArtifact): + return ListArtifact([task_input]) + elif isinstance(task_input, Callable): + return self._process_task_input(task_input(self)) + elif isinstance(task_input, str): + return self._process_task_input(TextArtifact(task_input)) + elif isinstance(task_input, (list, tuple)): + return ListArtifact([self._process_task_input(elem) for elem in task_input]) + else: + raise ValueError(f"Invalid input type: {type(task_input)} ") def __init_from_prompt(self, value: str) -> None: thought_matches = re.findall(self.THOUGHT_PATTERN, value, re.MULTILINE) actions_matches = re.findall(self.ACTIONS_PATTERN, value, re.DOTALL) answer_matches = re.findall(self.ANSWER_PATTERN, value, re.MULTILINE) - if self.thought is None and len(thought_matches) > 0: + if self.thought is None and thought_matches: self.thought = thought_matches[-1] self.__parse_actions(actions_matches) # If there are no actions to take but an answer is provided, set the answer as the output. - if len(self.actions) == 0 and self.output is None and len(answer_matches) > 0: + if len(self.actions) == 0 and self.output is None and answer_matches: self.output = TextArtifact(answer_matches[-1]) + def __init_from_artifacts(self, artifacts: ListArtifact) -> None: + """Parses the input Artifacts to extract the thought and actions. + Text Artifacts are used to extract the thought, and ToolAction Artifacts are used to extract the actions. + + Args: + artifacts: The input Artifacts. + Returns: + None + """ + self.actions = [ + self.__process_action_object(artifact.value.to_dict()) + for artifact in artifacts.value + if isinstance(artifact, ActionArtifact) + ] + + thoughts = [artifact.value for artifact in artifacts.value if isinstance(artifact, TextArtifact)] + if thoughts: + self.thought = thoughts[0] + def __parse_actions(self, actions_matches: list[str]) -> None: if len(actions_matches) == 0: return - try: data = actions_matches[-1] - actions_list: list = json.loads(data, strict=False) - - if isinstance(self.origin_task, ActionsSubtaskOriginMixin): - self.origin_task.actions_schema().validate(actions_list) - - for action_object in actions_list: - # Load action name; throw exception if the key is not present - action_tag = action_object["tag"] - - # Load action name; throw exception if the key is not present - action_name = action_object["name"] - - # Load action method; throw exception if the key is not present - action_path = action_object["path"] - - # Load optional input value; don't throw exceptions if key is not present - if "input" in action_object: - # The schema library has a bug, where something like `Or(str, None)` doesn't get - # correctly translated into JSON schema. For some optional input fields LLMs sometimes - # still provide null value, which trips up the validator. The temporary solution that - # works is to strip all key-values where value is null. - action_input = remove_null_values_in_dict_recursively(action_object["input"]) - else: - action_input = {} - - # Load the action itself - if isinstance(self.origin_task, ActionsSubtaskOriginMixin): - tool = self.origin_task.find_tool(action_name) - else: - raise Exception( - "ActionSubtask must be attached to a Task that implements ActionSubtaskOriginMixin." - ) - - new_action = ActionsSubtask.Action( - tag=action_tag, name=action_name, path=action_path, input=action_input, tool=tool - ) - - if new_action.tool and new_action.input: - self.__validate_action(new_action) - - # Don't forget to add it to the subtask actions list! - self.actions.append(new_action) - except SyntaxError as e: - self.structure.logger.error(f"Subtask {self.origin_task.id}\nSyntax error: {e}") + actions_list: list[dict] = json.loads(data, strict=False) - self.actions.append(self.__error_to_action(f"syntax error: {e}")) - except schema.SchemaError as e: - self.structure.logger.error(f"Subtask {self.origin_task.id}\nInvalid action JSON: {e}") + self.actions = [self.__process_action_object(action_object) for action_object in actions_list] + except json.JSONDecodeError as e: + self.structure.logger.error(f"Subtask {self.origin_task.id}\nInvalid actions JSON: {e}") - self.actions.append(self.__error_to_action(f"Action JSON validation error: {e}")) - except Exception as e: - self.structure.logger.error(f"Subtask {self.origin_task.id}\nError parsing tool action: {e}") + self.output = ErrorArtifact(f"Actions JSON decoding error: {e}", exception=e) + + def __process_action_object(self, action_object: dict) -> ToolAction: + # Load action tag; throw exception if the key is not present + action_tag = action_object["tag"] + + # Load action name; throw exception if the key is not present + action_name = action_object["name"] + + # Load action method; throw exception if the key is not present + action_path = action_object["path"] + + # Load optional input value; don't throw exceptions if key is not present + if "input" in action_object: + # Some LLMs don't support nested parameters and therefore won't generate "values". + # So we need to manually add it here. + if "values" not in action_object["input"]: + action_object["input"] = {"values": action_object["input"]} + + # The schema library has a bug, where something like `Or(str, None)` doesn't get + # correctly translated into JSON schema. For some optional input fields LLMs sometimes + # still provide null value, which trips up the validator. The temporary solution that + # works is to strip all key-values where value is null. + action_input = remove_null_values_in_dict_recursively(action_object["input"]) + else: + action_input = {} + + # Load the action itself + if isinstance(self.origin_task, ActionsSubtaskOriginMixin): + tool = self.origin_task.find_tool(action_name) + else: + raise Exception("ActionSubtask must be attached to a Task that implements ActionSubtaskOriginMixin.") + + action = ToolAction(tag=action_tag, name=action_name, path=action_path, input=action_input, tool=tool) - self.actions.append(self.__error_to_action(f"Action input parsing error: {e}")) + if action.tool and action.input: + self.__validate_action(action) - def __error_to_action(self, error: str) -> Action: - return ActionsSubtask.Action(tag="error", name="error", input={"error": error}) + return action - def __validate_action(self, action: Action) -> None: + def __validate_action(self, action: ToolAction) -> None: try: if action.path is not None: activity = getattr(action.tool, action.path) else: - raise Exception("Action path not found.") + raise Exception("ToolAction path not found.") if activity is not None: activity_schema = action.tool.activity_schema(activity) @@ -269,6 +291,10 @@ def __validate_action(self, action: Action) -> None: if activity_schema: activity_schema.validate(action.input) except schema.SchemaError as e: - self.structure.logger.error(f"Subtask {self.origin_task.id}\nInvalid activity input JSON: {e}") + self.structure.logger.error(f"Subtask {self.origin_task.id}\nInvalid action JSON: {e}") + + action.output = ErrorArtifact(f"Activity input JSON validation error: {e}", exception=e) + except SyntaxError as e: + self.structure.logger.error(f"Subtask {self.origin_task.id}\nSyntax error: {e}") - self.actions.append(self.__error_to_action(f"Activity input JSON validation error: {e}")) + action.output = ErrorArtifact(f"Syntax error: {e}", exception=e) diff --git a/griptape/tasks/tool_task.py b/griptape/tasks/tool_task.py index edd90c26e..da40fd31a 100644 --- a/griptape/tasks/tool_task.py +++ b/griptape/tasks/tool_task.py @@ -1,6 +1,6 @@ from __future__ import annotations -import re import json +import re from typing import Optional, TYPE_CHECKING from attrs import define, field from schema import Schema @@ -11,6 +11,7 @@ from griptape.tools import BaseTool from griptape.utils import J2 from griptape.mixins import ActionsSubtaskOriginMixin +from griptape.common import PromptStack if TYPE_CHECKING: from griptape.memory import TaskMemory @@ -25,6 +26,13 @@ class ToolTask(PromptTask, ActionsSubtaskOriginMixin): subtask: Optional[ActionsSubtask] = field(default=None, kw_only=True) task_memory: Optional[TaskMemory] = field(default=None, kw_only=True) + @property + def prompt_stack(self) -> PromptStack: + stack = super().prompt_stack + stack.tools = [self.tool] + + return stack + def __attrs_post_init__(self) -> None: if self.task_memory is not None: self.set_default_tools_memory(self.task_memory) @@ -42,36 +50,42 @@ def default_system_template_generator(self, _: PromptTask) -> str: rulesets=J2("rulesets/rulesets.j2").render(rulesets=self.all_rulesets), action_schema=utils.minify_json(json.dumps(self.tool.schema())), meta_memory=J2("memory/meta/meta_memory.j2").render(meta_memories=self.meta_memories), + use_native_tools=self.prompt_driver.use_native_tools, ) def actions_schema(self) -> Schema: return self._actions_schema_for_tools([self.tool]) def run(self) -> BaseArtifact: - prompt_output = self.prompt_driver.run(prompt_stack=self.prompt_stack).to_text() - action_matches = re.findall(self.ACTION_PATTERN, prompt_output, re.DOTALL) - - if action_matches: - try: - data = action_matches[-1] - action_dict = json.loads(data) - action_dict["tag"] = self.tool.name - subtask_input = J2("tasks/tool_task/subtask.j2").render(action_json=json.dumps(action_dict)) - subtask = self.add_subtask(ActionsSubtask(subtask_input)) - - subtask.before_run() - subtask.run() - subtask.after_run() - - if isinstance(subtask.output, ListArtifact): - self.output = subtask.output[0] - else: - self.output = InfoArtifact("No tool output") - except Exception as e: - self.output = ErrorArtifact(f"Error processing tool input: {e}", exception=e) - return self.output + result = self.prompt_driver.run(prompt_stack=self.prompt_stack) + + if self.prompt_driver.use_native_tools: + subtask_input = result.to_artifact() else: - return ErrorArtifact("No action found in prompt output.") + action_matches = re.findall(self.ACTION_PATTERN, result.to_text(), re.DOTALL) + + if not action_matches: + return ErrorArtifact("No action found in prompt output.") + data = action_matches[-1] + action_dict = json.loads(data) + + action_dict["tag"] = self.tool.name + subtask_input = J2("tasks/tool_task/subtask.j2").render(action_json=json.dumps(action_dict)) + + try: + subtask = self.add_subtask(ActionsSubtask(subtask_input)) + + subtask.before_run() + subtask.run() + subtask.after_run() + + if isinstance(subtask.output, ListArtifact): + self.output = subtask.output[0] + else: + self.output = InfoArtifact("No tool output") + except Exception as e: + self.output = ErrorArtifact(f"Error processing tool input: {e}", exception=e) + return self.output def find_tool(self, tool_name: str) -> BaseTool: if self.tool.name == tool_name: diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index cfad9f49f..0c5dce67c 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -5,12 +5,12 @@ from schema import Schema from griptape import utils -from griptape.artifacts import BaseArtifact, ErrorArtifact +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact, ListArtifact, ActionArtifact from griptape.mixins import ActionsSubtaskOriginMixin from griptape.tasks import ActionsSubtask from griptape.tasks import PromptTask from griptape.utils import J2 -from griptape.common import PromptStack +from griptape.common import PromptStack, ToolAction if TYPE_CHECKING: from griptape.tools import BaseTool @@ -62,7 +62,7 @@ def tool_output_memory(self) -> list[TaskMemory]: @property def prompt_stack(self) -> PromptStack: - stack = PromptStack() + stack = PromptStack(tools=self.tools) memory = self.structure.conversation_memory stack.add_system_message(self.generate_system_template(self)) @@ -73,8 +73,35 @@ def prompt_stack(self) -> PromptStack: stack.add_assistant_message(self.output.to_text()) else: for s in self.subtasks: - stack.add_assistant_message(self.generate_assistant_subtask_template(s)) - stack.add_user_message(self.generate_user_subtask_template(s)) + if self.prompt_driver.use_native_tools: + action_calls = [ + ToolAction(name=action.name, path=action.path, tag=action.tag, input=action.input) + for action in s.actions + ] + action_results = [ + ToolAction(name=action.name, path=action.path, tag=action.tag, output=action.output) + for action in s.actions + ] + + stack.add_assistant_message( + ListArtifact( + [ + *([TextArtifact(s.thought)] if s.thought else []), + *[ActionArtifact(a) for a in action_calls], + ] + ) + ) + stack.add_user_message( + ListArtifact( + [ + *[ActionArtifact(a) for a in action_results], + *([] if s.output else [TextArtifact("Please keep going")]), + ] + ) + ) + else: + stack.add_assistant_message(self.generate_assistant_subtask_template(s)) + stack.add_user_message(self.generate_user_subtask_template(s)) if memory: # inserting at index 1 to place memory right after system prompt @@ -99,6 +126,7 @@ def default_system_template_generator(self, _: PromptTask) -> str: action_names=str.join(", ", [tool.name for tool in self.tools]), actions_schema=utils.minify_json(json.dumps(schema)), meta_memory=J2("memory/meta/meta_memory.j2").render(meta_memories=self.meta_memories), + use_native_tools=self.prompt_driver.use_native_tools, stop_sequence=self.response_stop_sequence, ) @@ -133,7 +161,8 @@ def run(self) -> BaseArtifact: if self.response_stop_sequence not in self.prompt_driver.tokenizer.stop_sequences: self.prompt_driver.tokenizer.stop_sequences.extend([self.response_stop_sequence]) - subtask = self.add_subtask(ActionsSubtask(self.prompt_driver.run(prompt_stack=self.prompt_stack).to_text())) + result = self.prompt_driver.run(self.prompt_stack) + subtask = self.add_subtask(ActionsSubtask(result.to_artifact())) while True: if subtask.output is None: @@ -147,9 +176,8 @@ def run(self) -> BaseArtifact: subtask.run() subtask.after_run() - subtask = self.add_subtask( - ActionsSubtask(self.prompt_driver.run(prompt_stack=self.prompt_stack).to_text()) - ) + result = self.prompt_driver.run(prompt_stack=self.prompt_stack) + subtask = self.add_subtask(ActionsSubtask(result.to_artifact())) else: break diff --git a/griptape/templates/tasks/tool_task/system.j2 b/griptape/templates/tasks/tool_task/system.j2 index 996f89e1f..f56f869b3 100644 --- a/griptape/templates/tasks/tool_task/system.j2 +++ b/griptape/templates/tasks/tool_task/system.j2 @@ -1,6 +1,9 @@ -You must respond to requests by using the following Action Schema. Your response must ONLY be a plain JSON object that successfully validates against the schema. The schema is provided below: -Action Schema: {{ action_schema }} +You must respond to requests by using the actions. Your response must ONLY be a plain JSON object that successfully validates against the Action Schema. +{% if not use_native_tools %} +The schema is provided below: +Action Schema: {{ action_schema }} +{% endif %} {% if meta_memory %} {{ meta_memory }} diff --git a/griptape/templates/tasks/toolkit_task/system.j2 b/griptape/templates/tasks/toolkit_task/system.j2 index 8ddfcf407..09c4e9af9 100644 --- a/griptape/templates/tasks/toolkit_task/system.j2 +++ b/griptape/templates/tasks/toolkit_task/system.j2 @@ -1,14 +1,20 @@ -Think step-by-step and execute actions sequentially or in parallel. You must use the following format when executing actions: +You can think step-by-step and execute actions sequentially or in parallel to get your final answer. +{% if not use_native_tools %} + +You must use the following format when executing actions: Thought: Actions: {{ stop_sequence }}: ...repeat Thought/Actions/{{ stop_sequence }} as many times as you need -Answer: +"Thought", "Actions", "{{ stop_sequence }}" must always start on a new line. If {{ stop_sequence }} contains an error, you MUST ALWAYS try to fix the error with another Thought/Actions/{{ stop_sequence }}. -"Thought", "Actions", "{{ stop_sequence }}", and "Answer" MUST ALWAYS start on a new line. If {{ stop_sequence }} contains an error, you MUST ALWAYS try to fix the error with another Thought/Actions/{{ stop_sequence }}. NEVER make up actions. Actions must ALWAYS be a plain JSON array of objects. ALWAYS use double quotes for keys and string values in JSON objects. NEVER make up facts. Be truthful. ALWAYS be proactive and NEVER ask the user for more information input. Keep going until you have the final answer. +{% endif %} +You must use the following format when providing your final answer: +Answer: -You have access ONLY to the actions with the following names: [{{ action_names }}]. You can use multiple actions in a sequence or in parallel to get the final answer. NEVER make up action names or action paths. NEVER reference tags in other action input values. +Be truthful. ALWAYS be proactive and NEVER ask the user for more information input. Keep using actions until you have your final answer. +NEVER make up actions, action names, or action paths. NEVER make up facts. NEVER reference tags in other action input values. Actions might store their output in memory as artifacts (with `memory_name` and `artifact_namespace`). If action output is stored in memory, ALWAYS try to pass it to another action. NEVER make up memory names or artifact namespaces. {% if meta_memory %} diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 03aaf22b5..44db36f2a 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -11,6 +11,7 @@ import yaml from attrs import define, field, Factory from griptape.artifacts import BaseArtifact, InfoArtifact, TextArtifact +from griptape.common import ToolAction from griptape.mixins import ActivityMixin if TYPE_CHECKING: @@ -87,7 +88,7 @@ def abs_dir_path(self): def schema(self) -> dict: full_schema = Schema(Or(*self.activity_schemas()), description=f"{self.name} action schema.") - return full_schema.json_schema(f"{self.name} Action Schema") + return full_schema.json_schema(f"{self.name} ToolAction Schema") def activity_schemas(self) -> list[Schema]: return [ @@ -103,18 +104,18 @@ def activity_schemas(self) -> list[Schema]: for activity in self.activities() ] - def execute(self, activity: Callable, subtask: ActionsSubtask, action: ActionsSubtask.Action) -> BaseArtifact: + def execute(self, activity: Callable, subtask: ActionsSubtask, action: ToolAction) -> BaseArtifact: preprocessed_input = self.before_run(activity, subtask, action) output = self.run(activity, subtask, action, preprocessed_input) postprocessed_output = self.after_run(activity, subtask, action, output) return postprocessed_output - def before_run(self, activity: Callable, subtask: ActionsSubtask, action: ActionsSubtask.Action) -> Optional[dict]: + def before_run(self, activity: Callable, subtask: ActionsSubtask, action: ToolAction) -> Optional[dict]: return action.input def run( - self, activity: Callable, subtask: ActionsSubtask, action: ActionsSubtask.Action, value: Optional[dict] + self, activity: Callable, subtask: ActionsSubtask, action: ToolAction, value: Optional[dict] ) -> BaseArtifact: activity_result = activity(value) @@ -128,7 +129,7 @@ def run( return result def after_run( - self, activity: Callable, subtask: ActionsSubtask, action: ActionsSubtask.Action, value: BaseArtifact + self, activity: Callable, subtask: ActionsSubtask, action: ToolAction, value: BaseArtifact ) -> BaseArtifact: if value: if self.output_memory: diff --git a/griptape/utils/__init__.py b/griptape/utils/__init__.py index ceb19547e..19730ac3b 100644 --- a/griptape/utils/__init__.py +++ b/griptape/utils/__init__.py @@ -8,7 +8,7 @@ from .futures import execute_futures_dict from .futures import execute_futures_list from .token_counter import TokenCounter -from .dict_utils import remove_null_values_in_dict_recursively, dict_merge +from .dict_utils import remove_null_values_in_dict_recursively, dict_merge, remove_key_in_dict_recursively from .file_utils import load_file, load_files from .hash import str_to_hash from .import_utils import import_optional_dependency @@ -40,6 +40,7 @@ def minify_json(value: str) -> str: "TokenCounter", "remove_null_values_in_dict_recursively", "dict_merge", + "remove_key_in_dict_recursively", "Stream", "load_artifact_from_memory", "deprecation_warn", diff --git a/griptape/utils/dict_utils.py b/griptape/utils/dict_utils.py index a396bf7d1..42214a895 100644 --- a/griptape/utils/dict_utils.py +++ b/griptape/utils/dict_utils.py @@ -8,6 +8,13 @@ def remove_null_values_in_dict_recursively(d: dict) -> dict: return d +def remove_key_in_dict_recursively(d: dict, key: str) -> dict: + if isinstance(d, dict): + return {k: remove_key_in_dict_recursively(v, key) for k, v in d.items() if k != key} + else: + return d + + def dict_merge(dct: Optional[dict], merge_dct: Optional[dict], add_keys: bool = True) -> dict: """Recursive dict merge. Inspired by :meth:``dict.update()``, instead of updating only top-level keys, dict_merge recurses down into dicts nested diff --git a/poetry.lock b/poetry.lock index 8e52c6fca..8e11c84e5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1542,13 +1542,13 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "google-ai-generativelanguage" -version = "0.6.5" +version = "0.6.6" description = "Google Ai Generativelanguage API client library" optional = true python-versions = ">=3.7" files = [ - {file = "google-ai-generativelanguage-0.6.5.tar.gz", hash = "sha256:c4089c277fa4e26722f76ab03ee3039f28be8bf1c9be282948b9583a154c6d79"}, - {file = "google_ai_generativelanguage-0.6.5-py3-none-any.whl", hash = "sha256:236875bb4a6d6ebdba2f12bd9d5e776100fd913402157a47b5e9fb80a13f25a7"}, + {file = "google-ai-generativelanguage-0.6.6.tar.gz", hash = "sha256:1739f035caeeeca5c28f887405eec8690f3372daf79fecf26454a97a4f1733a8"}, + {file = "google_ai_generativelanguage-0.6.6-py3-none-any.whl", hash = "sha256:59297737931f073d55ce1268dcc6d95111ee62850349d2b6cde942b16a4fca5c"}, ] [package.dependencies] @@ -1646,16 +1646,16 @@ httplib2 = ">=0.19.0" [[package]] name = "google-generativeai" -version = "0.7.0" +version = "0.7.2" description = "Google Generative AI High level API client library and tools." optional = true python-versions = ">=3.9" files = [ - {file = "google_generativeai-0.7.0-py3-none-any.whl", hash = "sha256:7be4b634afeb8b6bebde1af7271e94d2af84d2d28b5988c7ed9921733c40fe63"}, + {file = "google_generativeai-0.7.2-py3-none-any.whl", hash = "sha256:3117d1ebc92ee77710d4bc25ab4763492fddce9b6332eb25d124cf5d8b78b339"}, ] [package.dependencies] -google-ai-generativelanguage = "0.6.5" +google-ai-generativelanguage = "0.6.6" google-api-core = "*" google-api-python-client = "*" google-auth = ">=2.15.0" @@ -6509,4 +6509,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "35d73438908ba9f1bf741ad03dde06c0c86a25873646447537440e4f50b5544c" +content-hash = "09d5503da93cfcba7fdb3cc462395d5a2754bace3cee33feef9002b5904d5493" diff --git a/pyproject.toml b/pyproject.toml index 757da88c1..c315e9ffa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ redis = { version = "^4.6.0", optional = true } opensearch-py = { version = "^2.3.1", optional = true } pgvector = { version = "^0.2.3", optional = true } psycopg2-binary = { version = "^2.9.9", optional = true } -google-generativeai = { version = "^0.7.0", optional = true } +google-generativeai = { version = "^0.7.2", optional = true } trafilatura = {version = "^1.6", optional = true} playwright = {version = "^1.42", optional = true} beautifulsoup4 = {version = "^4.12.3", optional = true} diff --git a/tests/unit/artifacts/test_action_artifact.py b/tests/unit/artifacts/test_action_artifact.py new file mode 100644 index 000000000..e415bbdaf --- /dev/null +++ b/tests/unit/artifacts/test_action_artifact.py @@ -0,0 +1,53 @@ +import json +import pytest +from griptape.common import ToolAction +from griptape.artifacts import ActionArtifact, BaseArtifact + + +class TestActionArtifact: + @pytest.fixture() + def action(self) -> ToolAction: + return ToolAction(tag="TestTag", name="TestName", path="TestPath", input={"foo": "bar"}) + + def test___add__(self, action): + with pytest.raises(NotImplementedError): + result = ActionArtifact(action) + ActionArtifact(action) + + def test_to_text(self, action): + assert ActionArtifact(action).to_text() == json.dumps(action.to_dict()) + + def test_to_dict(self, action): + assert ActionArtifact(action).to_dict()["value"] == { + "tag": "TestTag", + "name": "TestName", + "path": "TestPath", + "input": {"foo": "bar"}, + "type": "ToolAction", + } + + def test_from_dict(self, action): + assert BaseArtifact.from_dict(ActionArtifact(action).to_dict()).to_dict()["value"] == { + "tag": "TestTag", + "name": "TestName", + "path": "TestPath", + "input": {"foo": "bar"}, + "type": "ToolAction", + } + + def test_to_json(self, action): + assert json.loads(ActionArtifact(action).to_json())["value"] == { + "tag": "TestTag", + "name": "TestName", + "path": "TestPath", + "input": {"foo": "bar"}, + "type": "ToolAction", + } + + def test_from_json(self, action): + assert ActionArtifact.from_json(ActionArtifact(action).to_json()).to_dict()["value"] == { + "tag": "TestTag", + "name": "TestName", + "path": "TestPath", + "input": {"foo": "bar"}, + "type": "ToolAction", + } diff --git a/tests/unit/common/__init__.py b/tests/unit/common/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/common/contents/test_action_call_delta_message_content.py b/tests/unit/common/contents/test_action_call_delta_message_content.py new file mode 100644 index 000000000..d164d9006 --- /dev/null +++ b/tests/unit/common/contents/test_action_call_delta_message_content.py @@ -0,0 +1,25 @@ +from griptape.common.prompt_stack.contents.action_call_delta_message_content import ActionCallDeltaMessageContent + + +class TestActionCallDeltaMessageContent: + def test__str__(self): + content = ActionCallDeltaMessageContent() + assert str(content) == "" + + content.name = "TestName" + assert str(content) == "TestName" + + content.path = "test_path" + assert str(content) == "TestName.test_path" + + content.tag = "test_tag" + assert str(content) == "TestName.test_path (test_tag)" + + content.partial_input = "partial_input" + assert str(content) == "TestName.test_path (test_tag) partial_input" + + def test_missing_header__str__(self): + assert str(ActionCallDeltaMessageContent(partial_input="partial_input")) == "partial_input" + + def test_missing_input__str__(self): + assert str(ActionCallDeltaMessageContent(tag="tag", name="name", path="path")) == "name.path (tag)" diff --git a/tests/unit/common/contents/test_action_call_message_content.py b/tests/unit/common/contents/test_action_call_message_content.py new file mode 100644 index 000000000..2e2e69d27 --- /dev/null +++ b/tests/unit/common/contents/test_action_call_message_content.py @@ -0,0 +1,55 @@ +import pytest +from griptape.artifacts.action_artifact import ActionArtifact +from griptape.common import ActionCallMessageContent, ActionCallDeltaMessageContent, ToolAction + + +class TestActionCallMessageContent: + def test_init(self): + assert ActionCallMessageContent( + ActionArtifact(ToolAction(tag="TestTag", name="TestName", path="TestPath", input={"foo": "bar"})) + ).artifact.value.to_dict() == { + "type": "ToolAction", + "tag": "TestTag", + "name": "TestName", + "path": "TestPath", + "input": {"foo": "bar"}, + } + + def test_from_deltas(self): + deltas = [ + ActionCallDeltaMessageContent(tag="testtag"), + ActionCallDeltaMessageContent(name="TestName"), + ActionCallDeltaMessageContent(path="test_tag"), + ActionCallDeltaMessageContent(partial_input='{"foo":'), + ActionCallDeltaMessageContent(partial_input='"bar"}'), + ] + + assert ActionCallMessageContent.from_deltas(deltas).artifact.value.to_dict() == { + "type": "ToolAction", + "tag": "testtag", + "name": "TestName", + "path": "test_tag", + "input": {"foo": "bar"}, + } + + def test_from_missing_header(self): + deltas = [ + ActionCallDeltaMessageContent(tag="testtag"), + ActionCallDeltaMessageContent(name="TestName"), + ActionCallDeltaMessageContent(partial_input='{"foo":'), + ActionCallDeltaMessageContent(partial_input='"bar"}'), + ] + + with pytest.raises(ValueError, match="Missing required fields"): + ActionCallMessageContent.from_deltas(deltas) + + def test_from_bad_json(self): + deltas = [ + ActionCallDeltaMessageContent(tag="testtag"), + ActionCallDeltaMessageContent(name="TestName"), + ActionCallDeltaMessageContent(path="test_tag"), + ActionCallDeltaMessageContent(partial_input='{"foo":'), + ] + + with pytest.raises(ValueError, match="Invalid JSON"): + ActionCallMessageContent.from_deltas(deltas) diff --git a/tests/unit/common/contents/test_action_result_message_content.py b/tests/unit/common/contents/test_action_result_message_content.py new file mode 100644 index 000000000..b1bcc356d --- /dev/null +++ b/tests/unit/common/contents/test_action_result_message_content.py @@ -0,0 +1,18 @@ +import pytest +from griptape.artifacts.text_artifact import TextArtifact +from griptape.common import ActionResultMessageContent, ToolAction + + +class TestActionResultMessageContent: + def test_init(self): + assert ( + ActionResultMessageContent( + TextArtifact("foo"), + action=ToolAction(tag="TestTag", name="TestName", path="TestPath", input={"foo": "bar"}), + ).artifact.value + == "foo" + ) + + def test_from_deltas(self): + with pytest.raises(NotImplementedError): + ActionResultMessageContent.from_deltas([]) diff --git a/tests/unit/common/contents/test_base_message_content.py b/tests/unit/common/contents/test_base_message_content.py new file mode 100644 index 000000000..8f1e9cf9f --- /dev/null +++ b/tests/unit/common/contents/test_base_message_content.py @@ -0,0 +1,17 @@ +from griptape.artifacts.text_artifact import TextArtifact +from griptape.common import TextMessageContent + + +class TestBaseMessageContent: + def test__str__(self): + assert str(TextMessageContent(TextArtifact("foo"))) == "foo" + + def test__bool__(self): + assert bool(TextMessageContent(TextArtifact("foo"))) + assert not bool(TextMessageContent(TextArtifact(""))) + + def test__len__(self): + assert len(TextMessageContent(TextArtifact("foo"))) == 3 + + def test_to_text(self): + assert TextMessageContent(TextArtifact("foo")).to_text() == "foo" diff --git a/tests/unit/common/contents/test_image_message_content.py b/tests/unit/common/contents/test_image_message_content.py new file mode 100644 index 000000000..b6c1b4c4f --- /dev/null +++ b/tests/unit/common/contents/test_image_message_content.py @@ -0,0 +1,12 @@ +import pytest +from griptape.artifacts.image_artifact import ImageArtifact +from griptape.common import ImageMessageContent + + +class TestImageMessageContent: + def test_init(self): + assert ImageMessageContent(ImageArtifact(b"foo", format="jpg", width=100, height=100)).artifact.value == b"foo" + + def test_from_deltas(self): + with pytest.raises(NotImplementedError): + ImageMessageContent.from_deltas([]) diff --git a/tests/unit/common/contents/test_text_delta_message_content.py b/tests/unit/common/contents/test_text_delta_message_content.py new file mode 100644 index 000000000..8fedd2822 --- /dev/null +++ b/tests/unit/common/contents/test_text_delta_message_content.py @@ -0,0 +1,6 @@ +from griptape.common import TextDeltaMessageContent + + +class TestTextDeltaMessageContent: + def test_init(self): + assert TextDeltaMessageContent("foo").text == "foo" diff --git a/tests/unit/common/contents/test_text_message_content.py b/tests/unit/common/contents/test_text_message_content.py new file mode 100644 index 000000000..01a3c0fd4 --- /dev/null +++ b/tests/unit/common/contents/test_text_message_content.py @@ -0,0 +1,15 @@ +from griptape.artifacts.text_artifact import TextArtifact +from griptape.common import TextMessageContent, TextDeltaMessageContent + + +class TestTextMessageContent: + def test_init(self): + assert TextMessageContent(TextArtifact("foo")).artifact.value == "foo" + + def test_from_deltas(self): + assert ( + TextMessageContent.from_deltas( + [TextDeltaMessageContent("foo"), TextDeltaMessageContent("bar")] + ).artifact.value + == "foobar" + ) diff --git a/tests/unit/common/test_action.py b/tests/unit/common/test_action.py new file mode 100644 index 000000000..db5284839 --- /dev/null +++ b/tests/unit/common/test_action.py @@ -0,0 +1,33 @@ +import pytest +import json +from griptape.common import ToolAction + + +class TestAction: + @pytest.fixture() + def action(self) -> ToolAction: + return ToolAction(tag="TestTag", name="TestName", path="TestPath", input={"foo": "bar"}) + + def test__str__(self, action: ToolAction): + assert str(action) == json.dumps( + {"type": "ToolAction", "tag": "TestTag", "name": "TestName", "path": "TestPath", "input": {"foo": "bar"}} + ) + + def test_to_dict(self, action: ToolAction): + assert action.to_dict() == { + "tag": "TestTag", + "name": "TestName", + "path": "TestPath", + "input": {"foo": "bar"}, + "type": "ToolAction", + } + + def test_to_native_tool_name(self, action: ToolAction): + assert action.to_native_tool_name() == "TestName_TestPath" + + action.path = None + assert action.to_native_tool_name() == "TestName" + + def test_from_native_tool_name(self): + assert ToolAction.from_native_tool_name("TestName_TestPath") == ("TestName", "TestPath") + assert ToolAction.from_native_tool_name("TestName") == ("TestName", None) diff --git a/tests/unit/common/test_prompt_stack.py b/tests/unit/common/test_prompt_stack.py new file mode 100644 index 000000000..83a16e140 --- /dev/null +++ b/tests/unit/common/test_prompt_stack.py @@ -0,0 +1,90 @@ +import pytest + +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact, ActionArtifact +from griptape.common import ImageMessageContent, PromptStack, TextMessageContent +from griptape.common import ActionCallMessageContent +from griptape.common import ActionResultMessageContent, ToolAction + + +class TestPromptStack: + @pytest.fixture + def prompt_stack(self): + return PromptStack() + + def test_init(self): + assert PromptStack() + + def test_add_message(self, prompt_stack): + prompt_stack.add_message("foo", "role") + prompt_stack.add_message(TextArtifact("foo"), "role") + prompt_stack.add_message(ImageArtifact(b"foo", format="png", width=100, height=100), "role") + prompt_stack.add_message(ListArtifact([TextArtifact("foo"), TextArtifact("bar")]), "role") + prompt_stack.add_message( + ListArtifact( + [TextArtifact("foo"), ActionArtifact(ToolAction(tag="foo", name="bar", path="baz", input={}))] + ), + "role", + ) + prompt_stack.add_message( + ListArtifact( + [ + TextArtifact("foo"), + ActionArtifact(ToolAction(tag="foo", name="bar", path="baz", input={}, output=TextArtifact("qux"))), + ] + ), + "role", + ) + + assert prompt_stack.messages[0].role == "role" + assert isinstance(prompt_stack.messages[0].content[0], TextMessageContent) + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + assert prompt_stack.messages[1].role == "role" + assert isinstance(prompt_stack.messages[1].content[0], TextMessageContent) + assert prompt_stack.messages[1].content[0].artifact.value == "foo" + + assert prompt_stack.messages[2].role == "role" + assert isinstance(prompt_stack.messages[2].content[0], ImageMessageContent) + assert prompt_stack.messages[2].content[0].artifact.value == b"foo" + + assert prompt_stack.messages[3].role == "role" + assert isinstance(prompt_stack.messages[3].content[0], TextMessageContent) + assert prompt_stack.messages[3].content[0].artifact.value == "foo" + assert isinstance(prompt_stack.messages[3].content[1], TextMessageContent) + assert prompt_stack.messages[3].content[1].artifact.value == "bar" + + assert prompt_stack.messages[4].role == "role" + assert isinstance(prompt_stack.messages[4].content[0], TextMessageContent) + assert prompt_stack.messages[4].content[0].artifact.value == "foo" + assert isinstance(prompt_stack.messages[4].content[1], ActionCallMessageContent) + assert prompt_stack.messages[4].content[1].artifact.value.to_dict() == { + "tag": "foo", + "name": "bar", + "path": "baz", + "input": {}, + "type": "ToolAction", + } + + assert prompt_stack.messages[5].role == "role" + assert isinstance(prompt_stack.messages[5].content[0], TextMessageContent) + assert prompt_stack.messages[5].content[0].artifact.value == "foo" + assert isinstance(prompt_stack.messages[5].content[1], ActionResultMessageContent) + assert prompt_stack.messages[5].content[1].artifact.value == "qux" + + def test_add_system_message(self, prompt_stack): + prompt_stack.add_system_message("foo") + + assert prompt_stack.messages[0].role == "system" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + def test_add_user_message(self, prompt_stack): + prompt_stack.add_user_message("foo") + + assert prompt_stack.messages[0].role == "user" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" + + def test_add_assistant_message(self, prompt_stack): + prompt_stack.add_assistant_message("foo") + + assert prompt_stack.messages[0].role == "assistant" + assert prompt_stack.messages[0].content[0].artifact.value == "foo" diff --git a/tests/unit/config/test_amazon_bedrock_structure_config.py b/tests/unit/config/test_amazon_bedrock_structure_config.py index d75684829..824e6ce11 100644 --- a/tests/unit/config/test_amazon_bedrock_structure_config.py +++ b/tests/unit/config/test_amazon_bedrock_structure_config.py @@ -51,6 +51,8 @@ def test_to_dict(self, config): "stream": False, "temperature": 0.1, "type": "AmazonBedrockPromptDriver", + "tool_choice": {"auto": {}}, + "use_native_tools": True, }, "vector_store_driver": { "embedding_driver": { @@ -102,6 +104,8 @@ def test_to_dict_with_values(self, config_with_values): "stream": False, "temperature": 0.1, "type": "AmazonBedrockPromptDriver", + "tool_choice": {"auto": {}}, + "use_native_tools": True, }, "vector_store_driver": { "embedding_driver": { diff --git a/tests/unit/config/test_anthropic_structure_config.py b/tests/unit/config/test_anthropic_structure_config.py index 03f9775f6..b41309a83 100644 --- a/tests/unit/config/test_anthropic_structure_config.py +++ b/tests/unit/config/test_anthropic_structure_config.py @@ -23,11 +23,12 @@ def test_to_dict(self, config): "model": "claude-3-5-sonnet-20240620", "top_p": 0.999, "top_k": 250, + "use_native_tools": True, }, "image_generation_driver": {"type": "DummyImageGenerationDriver"}, "image_query_driver": { "type": "AnthropicImageQueryDriver", - "model": "claude-3-opus-20240229", + "model": "claude-3-5-sonnet-20240620", "max_tokens": 256, }, "embedding_driver": { diff --git a/tests/unit/config/test_azure_openai_structure_config.py b/tests/unit/config/test_azure_openai_structure_config.py index 7e06dc0f5..58d557fb9 100644 --- a/tests/unit/config/test_azure_openai_structure_config.py +++ b/tests/unit/config/test_azure_openai_structure_config.py @@ -33,6 +33,7 @@ def test_to_dict(self, config): "max_tokens": None, "stream": False, "user": "", + "use_native_tools": True, }, "conversation_memory_driver": None, "embedding_driver": { diff --git a/tests/unit/config/test_cohere_structure_config.py b/tests/unit/config/test_cohere_structure_config.py index 1dc585421..44ed3e4d8 100644 --- a/tests/unit/config/test_cohere_structure_config.py +++ b/tests/unit/config/test_cohere_structure_config.py @@ -21,6 +21,8 @@ def test_to_dict(self, config): "max_tokens": None, "stream": False, "model": "command-r", + "force_single_step": False, + "use_native_tools": True, }, "embedding_driver": { "type": "CohereEmbeddingDriver", diff --git a/tests/unit/config/test_google_structure_config.py b/tests/unit/config/test_google_structure_config.py index ad96f2a35..469493e2c 100644 --- a/tests/unit/config/test_google_structure_config.py +++ b/tests/unit/config/test_google_structure_config.py @@ -22,6 +22,8 @@ def test_to_dict(self, config): "model": "gemini-1.5-pro", "top_p": None, "top_k": None, + "tool_choice": "auto", + "use_native_tools": True, }, "image_generation_driver": {"type": "DummyImageGenerationDriver"}, "image_query_driver": {"type": "DummyImageQueryDriver"}, diff --git a/tests/unit/config/test_openai_structure_config.py b/tests/unit/config/test_openai_structure_config.py index 3dd1ac85f..19321006f 100644 --- a/tests/unit/config/test_openai_structure_config.py +++ b/tests/unit/config/test_openai_structure_config.py @@ -25,6 +25,7 @@ def test_to_dict(self, config): "max_tokens": None, "stream": False, "user": "", + "use_native_tools": True, }, "conversation_memory_driver": None, "embedding_driver": { diff --git a/tests/unit/config/test_structure_config.py b/tests/unit/config/test_structure_config.py index a420205f2..27aaf81c4 100644 --- a/tests/unit/config/test_structure_config.py +++ b/tests/unit/config/test_structure_config.py @@ -10,7 +10,13 @@ def config(self): def test_to_dict(self, config): assert config.to_dict() == { "type": "StructureConfig", - "prompt_driver": {"type": "DummyPromptDriver", "temperature": 0.1, "max_tokens": None, "stream": False}, + "prompt_driver": { + "type": "DummyPromptDriver", + "temperature": 0.1, + "max_tokens": None, + "stream": False, + "use_native_tools": False, + }, "conversation_memory_driver": None, "embedding_driver": {"type": "DummyEmbeddingDriver"}, "image_generation_driver": {"type": "DummyImageGenerationDriver"}, diff --git a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py index 3cd165140..4b8323969 100644 --- a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py @@ -1,17 +1,154 @@ import pytest -from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.artifacts import ImageArtifact, TextArtifact, ListArtifact, ErrorArtifact, ActionArtifact from griptape.common import PromptStack +from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction from griptape.drivers import AmazonBedrockPromptDriver +from tests.mocks.mock_tool.tool import MockTool + class TestAmazonBedrockPromptDriver: + BEDROCK_TOOLS = [ + { + "toolSpec": { + "description": "test description: foo", + "inputSchema": { + "json": { + "$id": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + } + }, + "name": "MockTool_test", + } + }, + { + "toolSpec": { + "description": "test description: foo", + "inputSchema": { + "json": { + "$id": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + } + }, + "name": "MockTool_test_error", + } + }, + { + "toolSpec": { + "description": "test description", + "inputSchema": { + "json": { + "$id": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": {}, + "required": [], + "type": "object", + } + }, + "name": "MockTool_test_list_output", + } + }, + { + "toolSpec": { + "description": "test description", + "inputSchema": { + "json": { + "$id": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": {}, + "required": [], + "type": "object", + } + }, + "name": "MockTool_test_no_schema", + } + }, + { + "toolSpec": { + "description": "test description: foo", + "inputSchema": { + "json": { + "$id": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + } + }, + "name": "MockTool_test_str_output", + } + }, + { + "toolSpec": { + "description": "test description", + "inputSchema": { + "json": { + "$id": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + } + }, + "name": "MockTool_test_without_default_memory", + } + }, + ] + @pytest.fixture def mock_converse(self, mocker): mock_converse = mocker.patch("boto3.Session").return_value.client.return_value.converse mock_converse.return_value = { - "output": {"message": {"content": [{"text": "model-output"}]}}, + "output": { + "message": { + "content": [ + {"text": "model-output"}, + {"toolUse": {"name": "MockTool_test", "toolUseId": "mock-id", "input": {"foo": "bar"}}}, + ] + } + }, "usage": {"inputTokens": 5, "outputTokens": 10}, } @@ -23,7 +160,15 @@ def mock_converse_stream(self, mocker): mock_converse_stream.return_value = { "stream": [ + {"contentBlockStart": {"contentBlockIndex": 0, "start": {"text": "model-output"}}}, {"contentBlockDelta": {"contentBlockIndex": 0, "delta": {"text": "model-output"}}}, + { + "contentBlockStart": { + "contentBlockIndex": 1, + "start": {"toolUse": {"name": "MockTool_test", "toolUseId": "mock-id"}}, + } + }, + {"contentBlockDelta": {"contentBlockIndex": 1, "delta": {"toolUse": {"input": '{"foo": "bar"}'}}}}, {"metadata": {"usage": {"inputTokens": 5, "outputTokens": 10}}}, ] } @@ -33,12 +178,77 @@ def mock_converse_stream(self, mocker): @pytest.fixture(params=[True, False]) def prompt_stack(self, request): prompt_stack = PromptStack() + prompt_stack.tools = [MockTool()] if request.param: prompt_stack.add_system_message("system-input") prompt_stack.add_user_message("user-input") - prompt_stack.add_user_message(TextArtifact("user-input")) - prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) prompt_stack.add_assistant_message("assistant-input") + prompt_stack.add_assistant_message( + ListArtifact( + [ + TextArtifact("thought"), + ActionArtifact(ToolAction(tag="MockTool_test", name="MockTool", path="test", input={"foo": "bar"})), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=TextArtifact("tool-output"), + ) + ), + TextArtifact("keep-going"), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=ListArtifact( + [ + TextArtifact("tool-output"), + ImageArtifact(value=b"image-data", format="png", width=100, height=100), + ] + ), + ) + ), + TextArtifact("keep-going"), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=ErrorArtifact("error"), + ) + ), + TextArtifact("keep-going"), + ] + ) + ) return prompt_stack @@ -46,33 +256,91 @@ def prompt_stack(self, request): def messages(self): return [ {"role": "user", "content": [{"text": "user-input"}]}, - {"role": "user", "content": [{"text": "user-input"}]}, - {"role": "user", "content": [{"image": {"format": "png", "source": {"bytes": b"image-data"}}}]}, + { + "role": "user", + "content": [{"text": "user-input"}, {"image": {"format": "png", "source": {"bytes": b"image-data"}}}], + }, {"role": "assistant", "content": [{"text": "assistant-input"}]}, + { + "content": [ + {"text": "thought"}, + {"toolUse": {"input": {"foo": "bar"}, "name": "MockTool_test", "toolUseId": "MockTool_test"}}, + ], + "role": "assistant", + }, + { + "content": [ + { + "toolResult": { + "content": [{"text": "tool-output"}], + "status": "success", + "toolUseId": "MockTool_test", + } + }, + {"text": "keep-going"}, + ], + "role": "user", + }, + { + "content": [ + { + "toolResult": { + "content": [ + {"text": "tool-output"}, + {"image": {"format": "png", "source": {"bytes": b"image-data"}}}, + ], + "status": "success", + "toolUseId": "MockTool_test", + } + }, + {"text": "keep-going"}, + ], + "role": "user", + }, + { + "content": [ + {"toolResult": {"content": [{"text": "error"}], "status": "error", "toolUseId": "MockTool_test"}}, + {"text": "keep-going"}, + ], + "role": "user", + }, ] - def test_try_run(self, mock_converse, prompt_stack, messages): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_run(self, mock_converse, prompt_stack, messages, use_native_tools): # Given - driver = AmazonBedrockPromptDriver(model="ai21.j2") + driver = AmazonBedrockPromptDriver(model="ai21.j2", use_native_tools=use_native_tools) # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_converse.assert_called_once_with( modelId=driver.model, messages=messages, - **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), inferenceConfig={"temperature": driver.temperature}, additionalModelRequestFields={}, + **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), + **( + {"toolConfig": {"tools": self.BEDROCK_TOOLS, "toolChoice": driver.tool_choice}} + if use_native_tools + else {} + ), ) - assert text_artifact.value == "model-output" - assert text_artifact.usage.input_tokens == 5 - assert text_artifact.usage.output_tokens == 10 + assert isinstance(message.value[0], TextArtifact) + assert message.value[0].value == "model-output" + assert isinstance(message.value[1], ActionArtifact) + assert message.value[1].value.tag == "mock-id" + assert message.value[1].value.name == "MockTool" + assert message.value[1].value.path == "test" + assert message.value[1].value.input == {"foo": "bar"} + assert message.usage.input_tokens == 5 + assert message.usage.output_tokens == 10 - def test_try_stream_run(self, mock_converse_stream, prompt_stack, messages): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_stream_run(self, mock_converse_stream, prompt_stack, messages, use_native_tools): # Given - driver = AmazonBedrockPromptDriver(model="ai21.j2", stream=True) + driver = AmazonBedrockPromptDriver(model="ai21.j2", stream=True, use_native_tools=use_native_tools) # When stream = driver.try_stream(prompt_stack) @@ -82,13 +350,30 @@ def test_try_stream_run(self, mock_converse_stream, prompt_stack, messages): mock_converse_stream.assert_called_once_with( modelId=driver.model, messages=messages, - **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), inferenceConfig={"temperature": driver.temperature}, additionalModelRequestFields={}, + **({"system": [{"text": "system-input"}]} if prompt_stack.system_messages else {"system": []}), + **( + {"toolConfig": {"tools": self.BEDROCK_TOOLS, "toolChoice": driver.tool_choice}} + if prompt_stack.tools and use_native_tools + else {} + ), ) + event = next(stream) + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "model-output" + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.tag == "mock-id" + assert event.content.name == "MockTool" + assert event.content.path == "test" + + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.partial_input == '{"foo": "bar"}' + event = next(stream) assert event.usage.input_tokens == 5 assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py index 858c05ee6..67b3af372 100644 --- a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py @@ -1,20 +1,129 @@ +from griptape.artifacts.error_artifact import ErrorArtifact from griptape.drivers import AnthropicPromptDriver -from griptape.common import PromptStack -from griptape.artifacts import TextArtifact, ImageArtifact, ListArtifact +from griptape.common import PromptStack, TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction +from griptape.artifacts import TextArtifact, ActionArtifact, ImageArtifact, ListArtifact from unittest.mock import Mock import pytest +from tests.mocks.mock_tool.tool import MockTool + class TestAnthropicPromptDriver: + ANTHROPIC_TOOLS = [ + { + "description": "test description: foo", + "input_schema": { + "$id": "Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + "name": "MockTool_test", + }, + { + "description": "test description: foo", + "input_schema": { + "$id": "Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + "name": "MockTool_test_error", + }, + { + "description": "test description", + "input_schema": { + "$id": "Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": {}, + "required": [], + "type": "object", + }, + "name": "MockTool_test_list_output", + }, + { + "description": "test description", + "input_schema": { + "$id": "Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": {}, + "required": [], + "type": "object", + }, + "name": "MockTool_test_no_schema", + }, + { + "description": "test description: foo", + "input_schema": { + "$id": "Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + "name": "MockTool_test_str_output", + }, + { + "description": "test description", + "input_schema": { + "$id": "Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + "name": "MockTool_test_without_default_memory", + }, + ] + @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("anthropic.Anthropic") + mock_tool_use = Mock(type="tool_use", id="mock-id", input={"foo": "bar"}) + mock_tool_use.name = "MockTool_test" mock_client.return_value = Mock( messages=Mock( create=Mock( return_value=Mock( - usage=Mock(input_tokens=5, output_tokens=10), content=[Mock(type="text", text="model-output")] + usage=Mock(input_tokens=5, output_tokens=10), + content=[Mock(type="text", text="model-output"), mock_tool_use], ) ) ) @@ -26,13 +135,29 @@ def mock_client(self, mocker): def mock_stream_client(self, mocker): mock_stream_client = mocker.patch("anthropic.Anthropic") + mock_tool_call_delta_header = Mock(type="tool_use", id="mock-id") + mock_tool_call_delta_header.name = "MockTool_test" + mock_stream_client.return_value = Mock( messages=Mock( create=Mock( return_value=iter( [ Mock(type="message_start", message=Mock(usage=Mock(input_tokens=5))), - Mock(type="content_block_delta", delta=Mock(type="text_delta", text="model-output")), + Mock( + type="content_block_start", + index=0, + content_block=Mock(type="text", text="model-output"), + ), + Mock( + type="content_block_delta", index=0, delta=Mock(type="text_delta", text="model-output") + ), + Mock(type="content_block_start", index=1, content_block=mock_tool_call_delta_header), + Mock( + type="content_block_delta", + index=1, + delta=Mock(type="input_json_delta", partial_json='{"foo": "bar"}'), + ), Mock(type="message_delta", usage=Mock(output_tokens=10)), ] ) @@ -42,104 +167,188 @@ def mock_stream_client(self, mocker): return mock_stream_client - @pytest.mark.parametrize("model", [("claude-2.1"), ("claude-2.0")]) - def test_init(self, model): - assert AnthropicPromptDriver(model=model, api_key="1234") - - @pytest.mark.parametrize( - "model", - [ - ("claude-instant-1.2"), - ("claude-2.1"), - ("claude-2.0"), - ("claude-3-opus"), - ("claude-3-sonnet"), - ("claude-3-haiku"), - ], - ) - @pytest.mark.parametrize("system_enabled", [True, False]) - def test_try_run(self, mock_client, model, system_enabled): - # Given + @pytest.fixture(params=[True, False]) + def prompt_stack(self, request): prompt_stack = PromptStack() - if system_enabled: + prompt_stack.tools = [MockTool()] + if request.param: prompt_stack.add_system_message("system-input") prompt_stack.add_user_message("user-input") - prompt_stack.add_user_message(TextArtifact("user-input")) - prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) + prompt_stack.add_user_message( + ListArtifact( + [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] + ) + ) prompt_stack.add_assistant_message("assistant-input") - driver = AnthropicPromptDriver(model=model, api_key="api-key") - expected_messages = [ - {"role": "user", "content": "user-input"}, + prompt_stack.add_assistant_message( + ListArtifact( + [ + TextArtifact("thought"), + ActionArtifact(ToolAction(tag="MockTool_test", name="MockTool", path="test", input={"foo": "bar"})), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=TextArtifact("tool-output"), + ) + ), + TextArtifact("keep-going"), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=ListArtifact( + [ + TextArtifact("tool-output"), + ImageArtifact(value=b"image-data", format="png", width=100, height=100), + ] + ), + ) + ), + TextArtifact("keep-going"), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=ErrorArtifact("error"), + ) + ), + TextArtifact("keep-going"), + ] + ) + ) + + return prompt_stack + + @pytest.fixture + def messages(self): + return [ {"role": "user", "content": "user-input"}, { "content": [ + {"type": "text", "text": "user-input"}, { "source": {"data": "aW1hZ2UtZGF0YQ==", "media_type": "image/png", "type": "base64"}, "type": "image", - } + }, ], "role": "user", }, {"role": "assistant", "content": "assistant-input"}, + { + "content": [ + {"text": "thought", "type": "text"}, + {"id": "MockTool_test", "input": {"foo": "bar"}, "name": "MockTool_test", "type": "tool_use"}, + ], + "role": "assistant", + }, + { + "content": [ + { + "content": [{"text": "tool-output", "type": "text"}], + "is_error": False, + "tool_use_id": "MockTool_test", + "type": "tool_result", + }, + {"text": "keep-going", "type": "text"}, + ], + "role": "user", + }, + { + "content": [ + { + "content": [ + {"text": "tool-output", "type": "text"}, + { + "source": {"data": "aW1hZ2UtZGF0YQ==", "media_type": "image/png", "type": "base64"}, + "type": "image", + }, + ], + "is_error": False, + "tool_use_id": "MockTool_test", + "type": "tool_result", + }, + {"text": "keep-going", "type": "text"}, + ], + "role": "user", + }, + { + "content": [ + { + "content": [{"text": "error", "type": "text"}], + "is_error": True, + "tool_use_id": "MockTool_test", + "type": "tool_result", + }, + {"text": "keep-going", "type": "text"}, + ], + "role": "user", + }, ] + def test_init(self): + assert AnthropicPromptDriver(model="claude-3-haiku", api_key="1234") + + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_run(self, mock_client, prompt_stack, messages, use_native_tools): + # Given + driver = AnthropicPromptDriver(model="claude-3-haiku", api_key="api-key", use_native_tools=use_native_tools) + # When message = driver.try_run(prompt_stack) # Then mock_client.return_value.messages.create.assert_called_once_with( - messages=expected_messages, + messages=messages, stop_sequences=[], model=driver.model, max_tokens=1000, temperature=0.1, top_p=0.999, top_k=250, - **{"system": "system-input"} if system_enabled else {}, + **{"system": "system-input"} if prompt_stack.system_messages else {}, + **{"tools": self.ANTHROPIC_TOOLS, "tool_choice": driver.tool_choice} if use_native_tools else {}, ) - assert message.value == "model-output" + assert isinstance(message.value[0], TextArtifact) + assert message.value[0].value == "model-output" + assert isinstance(message.value[1], ActionArtifact) + assert message.value[1].value.tag == "mock-id" + assert message.value[1].value.name == "MockTool" + assert message.value[1].value.path == "test" + assert message.value[1].value.input == {"foo": "bar"} assert message.usage.input_tokens == 5 assert message.usage.output_tokens == 10 - @pytest.mark.parametrize( - "model", - [ - ("claude-instant-1.2"), - ("claude-2.1"), - ("claude-2.0"), - ("claude-3-opus"), - ("claude-3-sonnet"), - ("claude-3-haiku"), - ], - ) - @pytest.mark.parametrize("system_enabled", [True, False]) - def test_try_stream_run(self, mock_stream_client, model, system_enabled): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_stream_run(self, mock_stream_client, prompt_stack, messages, use_native_tools): # Given - prompt_stack = PromptStack() - if system_enabled: - prompt_stack.add_system_message("system-input") - prompt_stack.add_user_message("user-input") - prompt_stack.add_user_message( - ListArtifact( - [TextArtifact("user-input"), ImageArtifact(value=b"image-data", format="png", width=100, height=100)] - ) + driver = AnthropicPromptDriver( + model="claude-3-haiku", api_key="api-key", stream=True, use_native_tools=use_native_tools ) - prompt_stack.add_assistant_message("assistant-input") - expected_messages = [ - {"role": "user", "content": "user-input"}, - { - "content": [ - {"type": "text", "text": "user-input"}, - { - "source": {"data": "aW1hZ2UtZGF0YQ==", "media_type": "image/png", "type": "base64"}, - "type": "image", - }, - ], - "role": "user", - }, - {"role": "assistant", "content": "assistant-input"}, - ] - driver = AnthropicPromptDriver(model=model, api_key="api-key", stream=True) # When stream = driver.try_stream(prompt_stack) @@ -147,7 +356,7 @@ def test_try_stream_run(self, mock_stream_client, model, system_enabled): # Then mock_stream_client.return_value.messages.create.assert_called_once_with( - messages=expected_messages, + messages=messages, stop_sequences=[], model=driver.model, max_tokens=1000, @@ -155,24 +364,28 @@ def test_try_stream_run(self, mock_stream_client, model, system_enabled): stream=True, top_p=0.999, top_k=250, - **{"system": "system-input"} if system_enabled else {}, + **{"system": "system-input"} if prompt_stack.system_messages else {}, + **{"tools": self.ANTHROPIC_TOOLS, "tool_choice": driver.tool_choice} if use_native_tools else {}, ) assert event.usage.input_tokens == 5 event = next(stream) + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "model-output" event = next(stream) - assert event.usage.output_tokens == 10 + assert isinstance(event.content, TextDeltaMessageContent) + assert event.content.text == "model-output" - def test_try_run_throws_when_prompt_stack_is_string(self): - # Given - prompt_stack = "prompt-stack" - driver = AnthropicPromptDriver(model="claude", api_key="api-key") + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.tag == "mock-id" + assert event.content.name == "MockTool" + assert event.content.path == "test" - # When - with pytest.raises(Exception) as e: - driver.try_run(prompt_stack) # pyright: ignore + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.partial_input == '{"foo": "bar"}' - # Then - assert e.value.args[0] == "'str' object has no attribute 'messages'" + event = next(stream) + assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py index 378ecc3da..9e56b39bd 100644 --- a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py @@ -1,6 +1,8 @@ import pytest +from griptape.artifacts import TextArtifact, ActionArtifact from unittest.mock import Mock from griptape.drivers import AzureOpenAiChatPromptDriver +from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent from tests.unit.drivers.prompt.test_openai_chat_prompt_driver import TestOpenAiChatPromptDriverFixtureMixin @@ -8,20 +10,52 @@ class TestAzureOpenAiChatPromptDriver(TestOpenAiChatPromptDriverFixtureMixin): @pytest.fixture def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create + mock_function = Mock(arguments='{"foo": "bar"}', id="mock-id") + mock_function.name = "MockTool_test" mock_chat_create.return_value = Mock( headers={}, - choices=[Mock(message=Mock(content="model-output"))], + choices=[ + Mock(message=Mock(content="model-output", tool_calls=[Mock(id="mock-id", function=mock_function)])) + ], usage=Mock(prompt_tokens=5, completion_tokens=10), ) + return mock_chat_create @pytest.fixture def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create + mock_tool_call_delta_header = Mock() + mock_tool_call_delta_header.name = "MockTool_test" + mock_tool_call_delta_body = Mock(arguments='{"foo": "bar"}') + mock_tool_call_delta_body.name = None + mock_chat_create.return_value = iter( [ - Mock(choices=[Mock(delta=Mock(content="model-output"))], usage=None), + Mock(choices=[Mock(delta=Mock(content="model-output", tool_calls=None))], usage=None), + Mock( + choices=[ + Mock( + delta=Mock( + content=None, + tool_calls=[Mock(index=0, id="mock-id", function=mock_tool_call_delta_header)], + ) + ) + ], + usage=None, + ), + Mock( + choices=[ + Mock( + delta=Mock( + content=None, tool_calls=[Mock(index=0, id=None, function=mock_tool_call_delta_body)] + ) + ) + ], + usage=None, + ), Mock(choices=None, usage=Mock(prompt_tokens=5, completion_tokens=10)), + Mock(choices=[Mock(delta=Mock(content=None, tool_calls=None))], usage=None), ] ) return mock_chat_create @@ -30,25 +64,44 @@ def test_init(self): assert AzureOpenAiChatPromptDriver(azure_endpoint="foobar", azure_deployment="foobar", model="gpt-4") assert AzureOpenAiChatPromptDriver(azure_endpoint="foobar", model="gpt-4").azure_deployment == "gpt-4" - def test_try_run(self, mock_chat_completion_create, prompt_stack, messages): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_run(self, mock_chat_completion_create, prompt_stack, messages, use_native_tools): # Given - driver = AzureOpenAiChatPromptDriver(azure_endpoint="endpoint", azure_deployment="deployment-id", model="gpt-4") + driver = AzureOpenAiChatPromptDriver( + azure_endpoint="endpoint", + azure_deployment="deployment-id", + model="gpt-4", + use_native_tools=use_native_tools, + ) # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( - model=driver.model, temperature=driver.temperature, user=driver.user, messages=messages + model=driver.model, + temperature=driver.temperature, + user=driver.user, + messages=messages, + **{"tools": self.OPENAI_TOOLS, "tool_choice": driver.tool_choice} if use_native_tools else {}, ) - assert text_artifact.value == "model-output" - assert text_artifact.usage.input_tokens == 5 - assert text_artifact.usage.output_tokens == 10 + assert isinstance(message.value[0], TextArtifact) + assert message.value[0].value == "model-output" + assert isinstance(message.value[1], ActionArtifact) + assert message.value[1].value.tag == "mock-id" + assert message.value[1].value.name == "MockTool" + assert message.value[1].value.path == "test" + assert message.value[1].value.input == {"foo": "bar"} - def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages, use_native_tools): # Given driver = AzureOpenAiChatPromptDriver( - azure_endpoint="endpoint", azure_deployment="deployment-id", model="gpt-4", stream=True + azure_endpoint="endpoint", + azure_deployment="deployment-id", + model="gpt-4", + stream=True, + use_native_tools=use_native_tools, ) # When @@ -57,11 +110,30 @@ def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, # Then mock_chat_completion_stream_create.assert_called_once_with( - model=driver.model, temperature=driver.temperature, user=driver.user, stream=True, messages=messages + model=driver.model, + temperature=driver.temperature, + user=driver.user, + stream=True, + messages=messages, + **{"tools": self.OPENAI_TOOLS, "tool_choice": driver.tool_choice} if use_native_tools else {}, ) + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "model-output" + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.tag == "mock-id" + assert event.content.name == "MockTool" + assert event.content.path == "test" + + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.partial_input == '{"foo": "bar"}' + event = next(stream) assert event.usage.input_tokens == 5 assert event.usage.output_tokens == 10 + event = next(stream) + assert isinstance(event.content, TextDeltaMessageContent) + assert event.content.text == "" diff --git a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py index d65775e8b..059aaffe5 100644 --- a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py @@ -2,16 +2,48 @@ import pytest -from griptape.common import PromptStack +from griptape.artifacts.action_artifact import ActionArtifact +from griptape.artifacts.list_artifact import ListArtifact +from griptape.artifacts.text_artifact import TextArtifact +from griptape.common import PromptStack, ToolAction from griptape.drivers import CoherePromptDriver +from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent +from tests.mocks.mock_tool.tool import MockTool class TestCoherePromptDriver: + COHERE_TOOLS = [ + { + "description": "test description: foo", + "name": "MockTool_test", + "parameter_definitions": {"test": {"required": True, "type": "string"}}, + }, + { + "description": "test description: foo", + "name": "MockTool_test_error", + "parameter_definitions": {"test": {"required": True, "type": "string"}}, + }, + {"description": "test description", "name": "MockTool_test_list_output", "parameter_definitions": {}}, + {"description": "test description", "name": "MockTool_test_no_schema", "parameter_definitions": {}}, + { + "description": "test description: foo", + "name": "MockTool_test_str_output", + "parameter_definitions": {"test": {"required": True, "type": "string"}}, + }, + { + "description": "test description", + "name": "MockTool_test_without_default_memory", + "parameter_definitions": {"test": {"required": True, "type": "string"}}, + }, + ] + @pytest.fixture def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value + mock_tool_call = Mock(parameters={"foo": "bar"}) + mock_tool_call.name = "MockTool_test" mock_client.chat.return_value = Mock( - text="model-output", meta=Mock(tokens=Mock(input_tokens=5, output_tokens=10)) + text="model-output", meta=Mock(tokens=Mock(input_tokens=5, output_tokens=10)), tool_calls=[mock_tool_call] ) return mock_client @@ -19,9 +51,16 @@ def mock_client(self, mocker): @pytest.fixture def mock_stream_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value + mock_tool_call_delta_header = Mock() + mock_tool_call_delta_header.name = "MockTool_test" + mock_tool_call_delta_body = Mock() + mock_tool_call_delta_body.name = None + mock_tool_call_delta_body.parameters = '{"foo": "bar"}' mock_client.chat_stream.return_value = iter( [ Mock(text="model-output", event_type="text-generation"), + Mock(text="model-output", event_type="tool-calls-chunk", tool_call_delta=mock_tool_call_delta_header), + Mock(text="model-output", event_type="tool-calls-chunk", tool_call_delta=mock_tool_call_delta_body), Mock(response=Mock(meta=Mock(tokens=Mock(input_tokens=5, output_tokens=10))), event_type="stream-end"), ] ) @@ -35,67 +74,161 @@ def mock_tokenizer(self, mocker): @pytest.fixture(params=[True, False]) def prompt_stack(self, request): prompt_stack = PromptStack() + prompt_stack.tools = [MockTool()] if request.param: prompt_stack.add_system_message("system-input") prompt_stack.add_user_message("user-input") prompt_stack.add_assistant_message("assistant-input") - prompt_stack.add_user_message("user-input") - prompt_stack.add_assistant_message("assistant-input") + prompt_stack.add_assistant_message( + ListArtifact( + [ + TextArtifact("thought"), + ActionArtifact(ToolAction(tag="MockTool_test", name="MockTool", path="test", input={"foo": "bar"})), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + TextArtifact("keep going"), + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=TextArtifact("tool-output"), + ) + ), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + TextArtifact("keep going"), + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=TextArtifact("tool-output"), + ) + ), + ] + ) + ) return prompt_stack def test_init(self): assert CoherePromptDriver(model="command", api_key="foobar") - def test_try_run(self, mock_client, prompt_stack): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_run(self, mock_client, prompt_stack, use_native_tools): # Given - driver = CoherePromptDriver(model="command", api_key="api-key") + driver = CoherePromptDriver(model="command", api_key="api-key", use_native_tools=use_native_tools) # When - text_artifact = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_client.chat.assert_called_once_with( chat_history=[ - {"content": [{"text": "user-input"}], "role": "USER"}, - {"content": [{"text": "assistant-input"}], "role": "CHATBOT"}, - {"content": [{"text": "user-input"}], "role": "USER"}, + {"message": "user-input", "role": "USER"}, + {"message": "assistant-input", "role": "CHATBOT"}, + { + "message": "thought", + "role": "CHATBOT", + "tool_calls": [{"name": "MockTool_test", "parameters": {"foo": "bar"}}], + }, + { + "message": "keep going", + "role": "TOOL", + "tool_results": [ + { + "call": {"name": "MockTool_test", "parameters": {"foo": "bar"}}, + "outputs": [{"text": "tool-output"}], + } + ], + }, ], max_tokens=None, - message="assistant-input", + message="keep going", + **({"tools": self.COHERE_TOOLS, "force_single_step": False} if use_native_tools else {}), **({"preamble": "system-input"} if prompt_stack.system_messages else {}), + tool_results=[ + {"call": {"name": "MockTool_test", "parameters": {"foo": "bar"}}, "outputs": [{"text": "tool-output"}]} + ], stop_sequences=[], temperature=0.1, ) - assert text_artifact.value == "model-output" - assert text_artifact.usage.input_tokens == 5 - assert text_artifact.usage.output_tokens == 10 + assert isinstance(message.value[0], TextArtifact) + assert message.value[0].value == "model-output" + assert isinstance(message.value[1], ActionArtifact) + assert message.value[1].value.tag == "MockTool_test" + assert message.value[1].value.name == "MockTool" + assert message.value[1].value.path == "test" + assert message.value[1].value.input == {"foo": "bar"} - def test_try_stream_run(self, mock_stream_client, prompt_stack): # pyright: ignore + assert message.usage.input_tokens == 5 + assert message.usage.output_tokens == 10 + + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_stream_run(self, mock_stream_client, prompt_stack, use_native_tools): # Given - driver = CoherePromptDriver(model="command", api_key="api-key", stream=True) + driver = CoherePromptDriver(model="command", api_key="api-key", stream=True, use_native_tools=use_native_tools) # When stream = driver.try_stream(prompt_stack) event = next(stream) # Then - mock_stream_client.chat_stream.assert_called_once_with( chat_history=[ - {"content": [{"text": "user-input"}], "role": "USER"}, - {"content": [{"text": "assistant-input"}], "role": "CHATBOT"}, - {"content": [{"text": "user-input"}], "role": "USER"}, + {"message": "user-input", "role": "USER"}, + {"message": "assistant-input", "role": "CHATBOT"}, + { + "message": "thought", + "role": "CHATBOT", + "tool_calls": [{"name": "MockTool_test", "parameters": {"foo": "bar"}}], + }, + { + "role": "TOOL", + "message": "keep going", + "tool_results": [ + { + "call": {"name": "MockTool_test", "parameters": {"foo": "bar"}}, + "outputs": [{"text": "tool-output"}], + } + ], + }, ], max_tokens=None, - message="assistant-input", + message="keep going", + **({"tools": self.COHERE_TOOLS, "force_single_step": False} if use_native_tools else {}), **({"preamble": "system-input"} if prompt_stack.system_messages else {}), + tool_results=[ + {"call": {"name": "MockTool_test", "parameters": {"foo": "bar"}}, "outputs": [{"text": "tool-output"}]} + ], stop_sequences=[], temperature=0.1, ) + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "model-output" + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.tag == "MockTool_test" + assert event.content.name == "MockTool" + assert event.content.path == "test" + + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.partial_input == '{"foo": "bar"}' + event = next(stream) assert event.usage.input_tokens == 5 assert event.usage.output_tokens == 10 diff --git a/tests/unit/drivers/prompt/test_google_prompt_driver.py b/tests/unit/drivers/prompt/test_google_prompt_driver.py index 6a25ec3d3..c4b341481 100644 --- a/tests/unit/drivers/prompt/test_google_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_google_prompt_driver.py @@ -1,17 +1,51 @@ -from google.generativeai.types import GenerationConfig -from griptape.artifacts import TextArtifact, ImageArtifact +from google.generativeai.types import ContentDict, GenerationConfig +from google.generativeai.protos import FunctionCall, FunctionResponse, Part +from griptape.artifacts import TextArtifact, ImageArtifact, ActionArtifact +from griptape.artifacts.list_artifact import ListArtifact +from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction from griptape.drivers import GooglePromptDriver from griptape.common import PromptStack from unittest.mock import Mock +from tests.mocks.mock_tool.tool import MockTool +from google.protobuf.json_format import MessageToDict + import pytest class TestGooglePromptDriver: + GOOGLE_TOOLS = [ + { + "name": "MockTool_test", + "description": "test description: foo", + "parameters": {"type": "OBJECT", "properties": {"test": {"type": "STRING"}}, "required": ["test"]}, + }, + { + "name": "MockTool_test_error", + "description": "test description: foo", + "parameters": {"type": "OBJECT", "properties": {"test": {"type": "STRING"}}, "required": ["test"]}, + }, + {"name": "MockTool_test_list_output", "description": "test description", "parameters": {"type": "OBJECT"}}, + {"name": "MockTool_test_no_schema", "description": "test description", "parameters": {"type": "OBJECT"}}, + { + "name": "MockTool_test_str_output", + "description": "test description: foo", + "parameters": {"type": "OBJECT", "properties": {"test": {"type": "STRING"}}, "required": ["test"]}, + }, + { + "name": "MockTool_test_without_default_memory", + "description": "test description", + "parameters": {"type": "OBJECT", "properties": {"test": {"type": "STRING"}}, "required": ["test"]}, + }, + ] + @pytest.fixture def mock_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") + mock_function_call = Mock(type="tool_use", id="MockTool_test", args={"foo": "bar"}) + mock_function_call.name = "MockTool_test" mock_generative_model.return_value.generate_content.return_value = Mock( - text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=10) + parts=[Mock(text="model-output", function_call=None), Mock(text=None, function_call=mock_function_call)], + usage_metadata=Mock(prompt_token_count=5, candidates_token_count=10), ) return mock_generative_model @@ -19,90 +53,171 @@ def mock_generative_model(self, mocker): @pytest.fixture def mock_stream_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") + mock_function_call_delta = Mock(type="tool_use", id="MockTool_test", args={"foo": "bar"}) + mock_function_call_delta.name = "MockTool_test" mock_generative_model.return_value.generate_content.return_value = iter( [ - Mock(text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5)), - Mock(text="model-output", usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5)), + Mock( + parts=[Mock(text="model-output")], + usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5), + ), + Mock( + parts=[Mock(text=None, function_call=mock_function_call_delta)], + usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5), + ), + Mock( + parts=[Mock(text="model-output")], + usage_metadata=Mock(prompt_token_count=5, candidates_token_count=5), + ), ] ) return mock_generative_model - def test_init(self): - driver = GooglePromptDriver(model="gemini-pro", api_key="1234") - assert driver - - @pytest.mark.parametrize("system_enabled", [True, False]) - def test_try_run(self, mock_generative_model, system_enabled): - # Given + @pytest.fixture(params=[True, False]) + def prompt_stack(self, request): prompt_stack = PromptStack() - if system_enabled: + prompt_stack.tools = [MockTool()] + if request.param: prompt_stack.add_system_message("system-input") prompt_stack.add_user_message("user-input") prompt_stack.add_user_message(TextArtifact("user-input")) prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) prompt_stack.add_assistant_message("assistant-input") - driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", top_p=0.5, top_k=50) - # When - text_artifact = driver.try_run(prompt_stack) + prompt_stack.add_assistant_message( + ListArtifact( + [ + TextArtifact("thought"), + ActionArtifact(ToolAction(tag="MockTool_test", name="MockTool", path="test", input={"foo": "bar"})), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=TextArtifact("tool-output", id="output"), + ) + ), + TextArtifact("keep-going"), + ] + ) + ) - # Then - messages = [ - *( - [{"parts": ["system-input", "user-input"], "role": "user"}] - if system_enabled - else [{"parts": ["user-input"], "role": "user"}] - ), + return prompt_stack + + @pytest.fixture + def messages(self): + return [ + {"parts": ["user-input"], "role": "user"}, {"parts": ["user-input"], "role": "user"}, {"parts": [{"data": b"image-data", "mime_type": "image/png"}], "role": "user"}, {"parts": ["assistant-input"], "role": "model"}, + { + "parts": ["thought", Part(function_call=FunctionCall(name="MockTool_test", args={"foo": "bar"}))], + "role": "model", + }, + { + "parts": [ + Part( + function_response=FunctionResponse( + name="MockTool_test", response=TextArtifact("tool-output", id="output").to_dict() + ) + ), + "keep-going", + ], + "role": "user", + }, ] - mock_generative_model.return_value.generate_content.assert_called_once_with( - messages, - generation_config=GenerationConfig( - max_output_tokens=None, temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[] - ), + + def test_init(self): + driver = GooglePromptDriver(model="gemini-pro", api_key="1234") + assert driver + + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_run(self, mock_generative_model, prompt_stack, messages, use_native_tools): + # Given + driver = GooglePromptDriver( + model="gemini-pro", api_key="api-key", top_p=0.5, top_k=50, use_native_tools=use_native_tools ) - assert text_artifact.value == "model-output" - assert text_artifact.usage.input_tokens == 5 - assert text_artifact.usage.output_tokens == 10 - @pytest.mark.parametrize("system_enabled", [True, False]) - def test_try_stream(self, mock_stream_generative_model, system_enabled): + # When + message = driver.try_run(prompt_stack) + + # Then + if prompt_stack.system_messages: + assert mock_generative_model.return_value._system_instruction == ContentDict( + role="system", parts=[Part(text="system-input")] + ) + mock_generative_model.return_value.generate_content.assert_called_once() + # We can't use assert_called_once_with because we can't compare the FunctionDeclaration objects + call_args = mock_generative_model.return_value.generate_content.call_args + assert messages == call_args.args[0] + generation_config = call_args.kwargs["generation_config"] + assert generation_config == GenerationConfig(temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[]) + if use_native_tools: + tool_declarations = call_args.kwargs["tools"] + assert [ + MessageToDict(tool_declaration.to_proto()._pb) for tool_declaration in tool_declarations + ] == self.GOOGLE_TOOLS + + assert isinstance(message.value[0], TextArtifact) + assert message.value[0].value == "model-output" + assert isinstance(message.value[1], ActionArtifact) + assert message.value[1].value.tag == "MockTool_test" + assert message.value[1].value.name == "MockTool" + assert message.value[1].value.path == "test" + assert message.value[1].value.input == {"foo": "bar"} + assert message.usage.input_tokens == 5 + assert message.usage.output_tokens == 10 + + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_stream(self, mock_stream_generative_model, prompt_stack, messages, use_native_tools): # Given - prompt_stack = PromptStack() - if system_enabled: - prompt_stack.add_system_message("system-input") - prompt_stack.add_user_message("user-input") - prompt_stack.add_user_message(TextArtifact("user-input")) - prompt_stack.add_user_message(ImageArtifact(value=b"image-data", format="png", width=100, height=100)) - prompt_stack.add_assistant_message("assistant-input") - driver = GooglePromptDriver(model="gemini-pro", api_key="api-key", stream=True, top_p=0.5, top_k=50) + driver = GooglePromptDriver( + model="gemini-pro", api_key="api-key", stream=True, top_p=0.5, top_k=50, use_native_tools=use_native_tools + ) # When stream = driver.try_stream(prompt_stack) # Then event = next(stream) - messages = [ - *( - [{"parts": ["system-input", "user-input"], "role": "user"}] - if system_enabled - else [{"parts": ["user-input"], "role": "user"}] - ), - {"parts": ["user-input"], "role": "user"}, - {"parts": [{"data": b"image-data", "mime_type": "image/png"}], "role": "user"}, - {"parts": ["assistant-input"], "role": "model"}, - ] - mock_stream_generative_model.return_value.generate_content.assert_called_once_with( - messages, - stream=True, - generation_config=GenerationConfig(temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[]), + if prompt_stack.system_messages: + assert mock_stream_generative_model.return_value._system_instruction == ContentDict( + role="system", parts=[Part(text="system-input")] + ) + # We can't use assert_called_once_with because we can't compare the FunctionDeclaration objects + mock_stream_generative_model.return_value.generate_content.assert_called_once() + call_args = mock_stream_generative_model.return_value.generate_content.call_args + + assert messages == call_args.args[0] + assert call_args.kwargs["stream"] is True + assert call_args.kwargs["generation_config"] == GenerationConfig( + temperature=0.1, top_p=0.5, top_k=50, stop_sequences=[] ) + if use_native_tools: + tool_declarations = call_args.kwargs["tools"] + assert [ + MessageToDict(tool_declaration.to_proto()._pb) for tool_declaration in tool_declarations + ] == self.GOOGLE_TOOLS + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "model-output" assert event.usage.input_tokens == 5 assert event.usage.output_tokens == 5 + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.tag == "MockTool_test" + assert event.content.name == "MockTool" + assert event.content.path == "test" + assert event.content.partial_input == '{"foo": "bar"}' + event = next(stream) assert event.usage.output_tokens == 5 diff --git a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py index 4618e1de3..ec7ea73f8 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py @@ -1,5 +1,5 @@ from griptape.drivers import HuggingFaceHubPromptDriver -from griptape.common import PromptStack +from griptape.common import PromptStack, TextDeltaMessageContent import pytest @@ -65,6 +65,7 @@ def test_try_stream(self, prompt_stack, mock_client_stream): event = next(stream) # Then + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "model-output" event = next(stream) diff --git a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py index 5c217ed06..9e664a398 100644 --- a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py @@ -1,20 +1,146 @@ from griptape.artifacts import ImageArtifact, ListArtifact -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, ActionArtifact from griptape.drivers import OpenAiChatPromptDriver -from griptape.common import PromptStack +from griptape.common import PromptStack, TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction from griptape.tokenizers import OpenAiTokenizer from unittest.mock import Mock from tests.mocks.mock_tokenizer import MockTokenizer +from tests.mocks.mock_tool.tool import MockTool import pytest class TestOpenAiChatPromptDriverFixtureMixin: + OPENAI_TOOLS = [ + { + "function": { + "description": "test description: foo", + "name": "MockTool_test", + "parameters": { + "$id": "Parameters Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + }, + "type": "function", + }, + { + "function": { + "description": "test description: foo", + "name": "MockTool_test_error", + "parameters": { + "$id": "Parameters Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + }, + "type": "function", + }, + { + "function": { + "description": "test description", + "name": "MockTool_test_list_output", + "parameters": { + "$id": "Parameters Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": {}, + "required": [], + "type": "object", + }, + }, + "type": "function", + }, + { + "function": { + "description": "test description", + "name": "MockTool_test_no_schema", + "parameters": { + "$id": "Parameters Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": {}, + "required": [], + "type": "object", + }, + }, + "type": "function", + }, + { + "function": { + "description": "test description: foo", + "name": "MockTool_test_str_output", + "parameters": { + "$id": "Parameters Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + }, + "type": "function", + }, + { + "function": { + "description": "test description", + "name": "MockTool_test_without_default_memory", + "parameters": { + "$id": "Parameters Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + }, + "type": "function", + }, + ] + @pytest.fixture def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create + mock_function = Mock(arguments='{"foo": "bar"}', id="mock-id") + mock_function.name = "MockTool_test" mock_chat_create.return_value = Mock( headers={}, - choices=[Mock(message=Mock(content="model-output"))], + choices=[ + Mock(message=Mock(content="model-output", tool_calls=[Mock(id="mock-id", function=mock_function)])) + ], usage=Mock(prompt_tokens=5, completion_tokens=10), ) @@ -23,11 +149,37 @@ def mock_chat_completion_create(self, mocker): @pytest.fixture def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create + mock_tool_call_delta_header = Mock() + mock_tool_call_delta_header.name = "MockTool_test" + mock_tool_call_delta_body = Mock(arguments='{"foo": "bar"}') + mock_tool_call_delta_body.name = None + mock_chat_create.return_value = iter( [ - Mock(choices=[Mock(delta=Mock(content="model-output"))], usage=None), + Mock(choices=[Mock(delta=Mock(content="model-output", tool_calls=None))], usage=None), + Mock( + choices=[ + Mock( + delta=Mock( + content=None, + tool_calls=[Mock(index=0, id="mock-id", function=mock_tool_call_delta_header)], + ) + ) + ], + usage=None, + ), + Mock( + choices=[ + Mock( + delta=Mock( + content=None, tool_calls=[Mock(index=0, id=None, function=mock_tool_call_delta_body)] + ) + ) + ], + usage=None, + ), Mock(choices=None, usage=Mock(prompt_tokens=5, completion_tokens=10)), - Mock(choices=[Mock(delta=Mock(content=None))], usage=None), + Mock(choices=[Mock(delta=Mock(content=None, tool_calls=None))], usage=None), ] ) return mock_chat_create @@ -35,6 +187,7 @@ def mock_chat_completion_stream_create(self, mocker): @pytest.fixture def prompt_stack(self): prompt_stack = PromptStack() + prompt_stack.tools = [MockTool()] prompt_stack.add_system_message("system-input") prompt_stack.add_user_message("user-input") prompt_stack.add_user_message( @@ -43,6 +196,30 @@ def prompt_stack(self): ) ) prompt_stack.add_assistant_message("assistant-input") + prompt_stack.add_assistant_message( + ListArtifact( + [ + TextArtifact("thought"), + ActionArtifact(ToolAction(tag="MockTool_test", name="MockTool", path="test", input={"foo": "bar"})), + ] + ) + ) + prompt_stack.add_user_message( + ListArtifact( + [ + TextArtifact("keep-going"), + ActionArtifact( + ToolAction( + tag="MockTool_test", + name="MockTool", + path="test", + input={"foo": "bar"}, + output=TextArtifact("tool-output"), + ) + ), + ] + ) + ) return prompt_stack @pytest.fixture @@ -58,6 +235,18 @@ def messages(self): ], }, {"role": "assistant", "content": "assistant-input"}, + { + "content": [{"text": "thought", "type": "text"}], + "role": "assistant", + "tool_calls": [ + { + "function": {"arguments": '{"foo": "bar"}', "name": "MockTool_test"}, + "id": "MockTool_test", + "type": "function", + } + ], + }, + {"content": "tool-output", "role": "tool", "tool_call_id": "MockTool_test"}, ] @@ -98,23 +287,37 @@ class TestOpenAiChatPromptDriver(TestOpenAiChatPromptDriverFixtureMixin): def test_init(self): assert OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_4_MODEL) - def test_try_run(self, mock_chat_completion_create, prompt_stack, messages): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_run(self, mock_chat_completion_create, prompt_stack, messages, use_native_tools): # Given - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) + driver = OpenAiChatPromptDriver( + model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, use_native_tools=use_native_tools + ) # When - event = driver.try_run(prompt_stack) + message = driver.try_run(prompt_stack) # Then mock_chat_completion_create.assert_called_once_with( - model=driver.model, temperature=driver.temperature, user=driver.user, messages=messages, seed=driver.seed + model=driver.model, + temperature=driver.temperature, + user=driver.user, + messages=messages, + seed=driver.seed, + **{"tools": self.OPENAI_TOOLS, "tool_choice": driver.tool_choice} if use_native_tools else {}, ) - assert event.value == "model-output" + assert isinstance(message.value[0], TextArtifact) + assert message.value[0].value == "model-output" + assert isinstance(message.value[1], ActionArtifact) + assert message.value[1].value.tag == "mock-id" + assert message.value[1].value.name == "MockTool" + assert message.value[1].value.path == "test" + assert message.value[1].value.input == {"foo": "bar"} def test_try_run_response_format(self, mock_chat_completion_create, prompt_stack, messages): # Given driver = OpenAiChatPromptDriver( - model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, response_format="json_object" + model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, response_format="json_object", use_native_tools=False ) # When @@ -129,13 +332,16 @@ def test_try_run_response_format(self, mock_chat_completion_create, prompt_stack seed=driver.seed, response_format={"type": "json_object"}, ) - assert message.value == "model-output" + assert message.value[0].value == "model-output" assert message.usage.input_tokens == 5 assert message.usage.output_tokens == 10 - def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages): + @pytest.mark.parametrize("use_native_tools", [True, False]) + def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages, use_native_tools): # Given - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, stream=True) + driver = OpenAiChatPromptDriver( + model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, stream=True, use_native_tools=use_native_tools + ) # When stream = driver.try_stream(prompt_stack) @@ -150,19 +356,34 @@ def test_try_stream_run(self, mock_chat_completion_stream_create, prompt_stack, messages=messages, seed=driver.seed, stream_options={"include_usage": True}, + **{"tools": self.OPENAI_TOOLS, "tool_choice": driver.tool_choice} if use_native_tools else {}, ) + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "model-output" + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.tag == "mock-id" + assert event.content.name == "MockTool" + assert event.content.path == "test" + + event = next(stream) + assert isinstance(event.content, ActionCallDeltaMessageContent) + assert event.content.partial_input == '{"foo": "bar"}' + event = next(stream) assert event.usage.input_tokens == 5 assert event.usage.output_tokens == 10 event = next(stream) + assert isinstance(event.content, TextDeltaMessageContent) assert event.content.text == "" def test_try_run_with_max_tokens(self, mock_chat_completion_create, prompt_stack, messages): # Given - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, max_tokens=1) + driver = OpenAiChatPromptDriver( + model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, max_tokens=1, use_native_tools=False + ) # When event = driver.try_run(prompt_stack) @@ -176,18 +397,7 @@ def test_try_run_with_max_tokens(self, mock_chat_completion_create, prompt_stack max_tokens=1, seed=driver.seed, ) - assert event.value == "model-output" - - def test_try_run_throws_when_prompt_stack_is_string(self): - # Given - driver = OpenAiChatPromptDriver(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL) - - # When - with pytest.raises(Exception) as e: - driver.try_run("prompt-stack") # pyright: ignore - - # Then - assert e.value.args[0] == "'str' object has no attribute 'messages'" + assert event.value[0].value == "model-output" def test_try_run_throws_when_multiple_choices_returned(self, mock_chat_completion_create, prompt_stack): # Given @@ -206,6 +416,7 @@ def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messa model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL, tokenizer=MockTokenizer(model="mock-model", stop_sequences=["mock-stop"]), max_tokens=1, + use_native_tools=False, ) # When @@ -221,4 +432,4 @@ def test_custom_tokenizer(self, mock_chat_completion_create, prompt_stack, messa seed=driver.seed, max_tokens=1, ) - assert event.value == "model-output" + assert event.value[0].value == "model-output" diff --git a/tests/unit/tasks/test_actions_subtask.py b/tests/unit/tasks/test_actions_subtask.py index 8b231d85f..ede892e2d 100644 --- a/tests/unit/tasks/test_actions_subtask.py +++ b/tests/unit/tasks/test_actions_subtask.py @@ -1,7 +1,10 @@ import json +from griptape.artifacts import ListArtifact, TextArtifact, ActionArtifact +from griptape.artifacts.error_artifact import ErrorArtifact from tests.mocks.mock_tool.tool import MockTool from griptape.tasks import ToolkitTask, ActionsSubtask from griptape.structures import Agent +from griptape.common import ToolAction class TestActionsSubtask: @@ -22,6 +25,58 @@ def test_basic_input(self): assert json_dict[0]["path"] == "test" assert json_dict[0]["input"] == {"values": {"test": "value"}} + def test_action_input(self): + valid_input = ActionArtifact( + ToolAction(tag="foo", name="MockTool", path="test", input={"values": {"test": "value"}}) + ) + task = ToolkitTask(tools=[MockTool()]) + Agent().add_task(task) + subtask = task.add_subtask(ActionsSubtask(valid_input)) + json_dict = json.loads(subtask.actions_to_json()) + + assert subtask.thought is None + assert json_dict[0]["name"] == "MockTool" + assert json_dict[0]["path"] == "test" + assert json_dict[0]["input"] == {"values": {"test": "value"}} + + def test_action_and_thought_input(self): + valid_input = ListArtifact( + [ + TextArtifact("thought"), + ActionArtifact( + ToolAction(tag="foo", name="MockTool", path="test", input={"values": {"test": "value"}}) + ), + ] + ) + task = ToolkitTask(tools=[MockTool()]) + Agent().add_task(task) + subtask = task.add_subtask(ActionsSubtask(valid_input)) + json_dict = json.loads(subtask.actions_to_json()) + + assert subtask.thought == "thought" + assert json_dict[0]["name"] == "MockTool" + assert json_dict[0]["path"] == "test" + assert json_dict[0]["input"] == {"values": {"test": "value"}} + + def test_callable_input(self): + valid_input = ListArtifact( + [ + TextArtifact("thought"), + ActionArtifact( + ToolAction(tag="foo", name="MockTool", path="test", input={"values": {"test": "value"}}) + ), + ] + ) + task = ToolkitTask(tools=[MockTool()]) + Agent().add_task(task) + subtask = task.add_subtask(ActionsSubtask(lambda task: valid_input)) + json_dict = json.loads(subtask.actions_to_json()) + + assert subtask.thought == "thought" + assert json_dict[0]["name"] == "MockTool" + assert json_dict[0]["path"] == "test" + assert json_dict[0]["input"] == {"values": {"test": "value"}} + def test_input_with_multiline_actions(self): valid_input = ( "Thought: need to test\n" @@ -87,7 +142,23 @@ def test_invalid_actions(self): task = ToolkitTask(tools=[MockTool()]) Agent().add_task(task) subtask = task.add_subtask(ActionsSubtask(invalid_input)) + + assert isinstance(subtask.output, ErrorArtifact) + assert "Actions JSON decoding error" in subtask.output.value + + def test_implicit_values(self): + valid_input = ( + "Thought: need to test\n" + 'Actions:[{"tag": "foo", "name": "MockTool","path": "test","input": {"test":\n"value"}}]' + "Response: test response\n" + "Answer: test output" + ) + + task = ToolkitTask(tools=[MockTool()]) + Agent().add_task(task) + subtask = task.add_subtask(ActionsSubtask(valid_input)) json_dict = json.loads(subtask.actions_to_json()) - assert json_dict[0]["name"] == "error" - assert "Action input parsing error" in json_dict[0]["input"]["error"] + assert json_dict[0]["name"] == "MockTool" + assert json_dict[0]["path"] == "test" + assert json_dict[0]["input"] == {"values": {"test": "value"}} diff --git a/tests/unit/tasks/test_toolkit_task.py b/tests/unit/tasks/test_toolkit_task.py index cc05a5caf..38002553c 100644 --- a/tests/unit/tasks/test_toolkit_task.py +++ b/tests/unit/tasks/test_toolkit_task.py @@ -1,6 +1,7 @@ from griptape.artifacts import ErrorArtifact, TextArtifact from griptape.structures import Agent from griptape.tasks import ToolkitTask, ActionsSubtask, PromptTask +from griptape.common import ToolAction from tests.mocks.mock_tool.tool import MockTool from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.utils import defaults @@ -160,7 +161,7 @@ def test_run(self): assert result.output_task.output.to_text() == "done" def test_run_max_subtasks(self): - output = """Actions: [{"name": "blah"}]""" + output = 'Actions: [{"tag": "foo", "name": "Tool1", "path": "test", "input": {"values": {"test": "value"}}}]' task = ToolkitTask("test", tools=[MockTool(name="Tool1")], max_subtasks=3) agent = Agent(prompt_driver=MockPromptDriver(mock_output=output)) @@ -221,10 +222,10 @@ def test_init_from_prompt_2(self): def test_add_subtask(self): task = ToolkitTask("test", tools=[MockTool(name="Tool1")]) subtask1 = ActionsSubtask( - "test1", actions=[ActionsSubtask.Action(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] + "test1", actions=[ToolAction(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] ) subtask2 = ActionsSubtask( - "test2", actions=[ActionsSubtask.Action(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] + "test2", actions=[ToolAction(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] ) Agent().add_task(task) @@ -245,10 +246,10 @@ def test_add_subtask(self): def test_find_subtask(self): task = ToolkitTask("test", tools=[MockTool(name="Tool1")]) subtask1 = ActionsSubtask( - "test1", actions=[ActionsSubtask.Action(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] + "test1", actions=[ToolAction(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] ) subtask2 = ActionsSubtask( - "test2", actions=[ActionsSubtask.Action(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] + "test2", actions=[ToolAction(tag="foo", name="test", path="test", input={"values": {"f": "b"}})] ) Agent().add_task(task) diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index 210780729..4b9b97260 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -4,6 +4,7 @@ import yaml from schema import SchemaMissingKeyError, Schema, Or from griptape.tasks import ActionsSubtask, ToolkitTask +from griptape.common import ToolAction from tests.mocks.mock_tool.tool import MockTool from tests.utils import defaults @@ -125,7 +126,7 @@ class TestBaseTool: "additionalProperties": False, }, ], - "$id": "MockTool Action Schema", + "$id": "MockTool ToolAction Schema", "$schema": "http://json-schema.org/draft-07/schema#", } @@ -206,7 +207,7 @@ def test_find_input_memory(self): assert MockTool(input_memory=[defaults.text_task_memory("foo")]).find_input_memory("foo") is not None def test_execute(self, tool): - action = ActionsSubtask.Action(input={}, name="", tag="") + action = ToolAction(input={}, name="", tag="") assert tool.execute(tool.test_list_output, ActionsSubtask("foo"), action).to_text() == "foo\n\nbar" def test_schema(self, tool): @@ -219,6 +220,6 @@ def test_activity_schemas(self, tool): full_schema = Schema(Or(*tool.activity_schemas()), description=f"{tool.name} action schema.") - tool_schema = full_schema.json_schema(f"{tool.name} Action Schema") + tool_schema = full_schema.json_schema(f"{tool.name} ToolAction Schema") assert tool_schema == self.TARGET_TOOL_SCHEMA diff --git a/tests/unit/utils/test_dict_utils.py b/tests/unit/utils/test_dict_utils.py index 958e0295b..4b4e4ca08 100644 --- a/tests/unit/utils/test_dict_utils.py +++ b/tests/unit/utils/test_dict_utils.py @@ -1,4 +1,4 @@ -from griptape.utils import remove_null_values_in_dict_recursively, dict_merge +from griptape.utils import remove_null_values_in_dict_recursively, dict_merge, remove_key_in_dict_recursively import pytest @@ -10,6 +10,13 @@ def test_remove_null_values_in_dict_recursively(self): assert remove_null_values_in_dict_recursively(dict_with_nones) == dict_without_nones + def test_remove_key_in_dict_recursively(self): + dict_with_key = {"foo": 1, "bar": {"baz": {"quxx": [1, 2, 3], "bar": 2}}} + + dict_without_key = {"foo": 1, "bar": {"baz": {"bar": 2}}} + + assert remove_key_in_dict_recursively(dict_with_key, "quxx") == dict_without_key + def test_dict_merge_merges_dicts(self): a = {"a": 1, "b": {"b1": 2, "b2": 3}} b = {"a": 1, "b": {"b1": 4}} From 0389725ffdd25f77ea432e8ac432b6542b27abe3 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 11 Jul 2024 07:41:32 -0700 Subject: [PATCH 53/87] Enable flake8 type check (#960) --- griptape/common/actions/tool_action.py | 2 +- .../contents/action_call_message_content.py | 5 ++- .../contents/action_result_message_content.py | 7 ++- .../contents/base_message_content.py | 4 +- .../contents/image_message_content.py | 7 ++- .../contents/text_message_content.py | 5 ++- .../prompt_stack/messages/base_message.py | 6 ++- .../prompt_stack/messages/delta_message.py | 6 ++- griptape/config/base_structure_config.py | 24 +++++----- .../base_audio_transcription_driver.py | 2 +- .../amazon_bedrock_cohere_embedding_driver.py | 2 +- .../amazon_bedrock_titan_embedding_driver.py | 2 +- .../embedding/base_embedding_driver.py | 8 ++-- .../base_event_listener_driver.py | 6 ++- .../base_image_generation_driver.py | 2 +- .../openai_image_generation_driver.py | 6 ++- .../base_image_generation_model_driver.py | 6 ++- ...diffusion_image_generation_model_driver.py | 6 ++- ...ock_titan_image_generation_model_driver.py | 6 ++- .../amazon_bedrock_image_query_driver.py | 2 +- .../image_query/base_image_query_driver.py | 2 +- .../base_image_query_model_driver.py | 5 ++- .../prompt/amazon_bedrock_prompt_driver.py | 2 +- ...mazon_sagemaker_jumpstart_prompt_driver.py | 2 +- .../drivers/prompt/anthropic_prompt_driver.py | 2 +- griptape/drivers/prompt/base_prompt_driver.py | 4 +- .../drivers/prompt/cohere_prompt_driver.py | 2 +- .../drivers/prompt/dummy_prompt_driver.py | 7 ++- .../drivers/prompt/google_prompt_driver.py | 4 +- .../prompt/huggingface_hub_prompt_driver.py | 2 +- .../huggingface_pipeline_prompt_driver.py | 2 +- .../drivers/prompt/ollama_prompt_driver.py | 2 +- .../prompt/openai_chat_prompt_driver.py | 2 +- .../drivers/rerank/cohere_rerank_driver.py | 2 +- .../base_text_to_speech_driver.py | 2 +- .../vector/base_vector_store_driver.py | 6 ++- .../vector/marqo_vector_store_driver.py | 2 +- .../engines/audio/text_to_speech_engine.py | 7 ++- .../extraction/base_extraction_engine.py | 10 +++-- .../extraction/csv_extraction_engine.py | 6 ++- .../extraction/json_extraction_engine.py | 6 ++- .../image/base_image_generation_engine.py | 10 +++-- .../inpainting_image_generation_engine.py | 8 ++-- .../outpainting_image_generation_engine.py | 8 ++-- .../image/prompt_image_generation_engine.py | 8 ++-- .../variation_image_generation_engine.py | 8 ++-- .../text_loader_retrieval_rag_module.py | 5 ++- .../vector_store_retrieval_rag_module.py | 7 +-- griptape/engines/rag/rag_context.py | 2 +- griptape/events/base_actions_subtask_event.py | 4 +- griptape/events/base_task_event.py | 6 ++- griptape/events/event_listener.py | 2 +- griptape/loaders/base_loader.py | 8 ++-- griptape/loaders/base_text_loader.py | 8 ++-- griptape/loaders/csv_loader.py | 6 ++- griptape/loaders/dataframe_loader.py | 2 +- griptape/loaders/text_loader.py | 6 ++- griptape/loaders/web_loader.py | 5 ++- .../structure/base_conversation_memory.py | 2 +- .../task/storage/base_artifact_storage.py | 6 ++- .../task/storage/text_artifact_storage.py | 2 +- griptape/mixins/serializable_mixin.py | 6 ++- griptape/schemas/base_schema.py | 45 +++++++++++++++---- griptape/structures/agent.py | 4 +- griptape/structures/structure.py | 6 +-- griptape/structures/workflow.py | 6 ++- griptape/tasks/audio_transcription_task.py | 5 ++- griptape/tasks/base_image_generation_task.py | 5 ++- griptape/tasks/extraction_task.py | 7 ++- griptape/tasks/rag_task.py | 5 ++- griptape/tasks/structure_run_task.py | 7 ++- griptape/tasks/text_to_speech_task.py | 8 ++-- griptape/tasks/tool_task.py | 6 +-- griptape/tasks/toolkit_task.py | 2 +- .../tools/audio_transcription_client/tool.py | 6 ++- griptape/tools/base_tool.py | 2 +- griptape/tools/image_query_client/tool.py | 6 ++- .../tool.py | 6 ++- .../tool.py | 6 ++- .../prompt_image_generation_client/tool.py | 7 ++- griptape/tools/rag_client/tool.py | 5 ++- griptape/tools/sql_client/tool.py | 6 ++- griptape/tools/structure_run_client/tool.py | 5 ++- griptape/tools/text_to_speech_client/tool.py | 8 ++-- .../variation_image_generation_client/tool.py | 6 ++- griptape/tools/vector_store_client/tool.py | 6 ++- griptape/tools/web_search/tool.py | 5 ++- griptape/utils/stream.py | 4 +- pyproject.toml | 1 + 89 files changed, 325 insertions(+), 172 deletions(-) diff --git a/griptape/common/actions/tool_action.py b/griptape/common/actions/tool_action.py index db1e29f74..2b03a10bb 100644 --- a/griptape/common/actions/tool_action.py +++ b/griptape/common/actions/tool_action.py @@ -4,10 +4,10 @@ from attrs import define, field -from griptape.artifacts import BaseArtifact from griptape.common import BaseAction if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact from griptape.tools import BaseTool diff --git a/griptape/common/prompt_stack/contents/action_call_message_content.py b/griptape/common/prompt_stack/contents/action_call_message_content.py index 9f8082d72..55cc78324 100644 --- a/griptape/common/prompt_stack/contents/action_call_message_content.py +++ b/griptape/common/prompt_stack/contents/action_call_message_content.py @@ -1,13 +1,16 @@ from __future__ import annotations import json -from collections.abc import Sequence from attrs import define, field from griptape.common import ToolAction from griptape.artifacts import ActionArtifact from griptape.common import BaseDeltaMessageContent, BaseMessageContent, ActionCallDeltaMessageContent +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from collections.abc import Sequence @define diff --git a/griptape/common/prompt_stack/contents/action_result_message_content.py b/griptape/common/prompt_stack/contents/action_result_message_content.py index 871649aea..8f75daaac 100644 --- a/griptape/common/prompt_stack/contents/action_result_message_content.py +++ b/griptape/common/prompt_stack/contents/action_result_message_content.py @@ -1,11 +1,14 @@ from __future__ import annotations -from collections.abc import Sequence from attrs import define, field -from griptape.artifacts import BaseArtifact from griptape.common import BaseDeltaMessageContent, BaseMessageContent, ToolAction +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact + from collections.abc import Sequence @define diff --git a/griptape/common/prompt_stack/contents/base_message_content.py b/griptape/common/prompt_stack/contents/base_message_content.py index f24f5229b..5515ef745 100644 --- a/griptape/common/prompt_stack/contents/base_message_content.py +++ b/griptape/common/prompt_stack/contents/base_message_content.py @@ -1,13 +1,13 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Sequence from typing import TYPE_CHECKING from attrs import define, field from griptape.mixins import SerializableMixin -from .base_delta_message_content import BaseDeltaMessageContent if TYPE_CHECKING: + from .base_delta_message_content import BaseDeltaMessageContent + from collections.abc import Sequence from griptape.artifacts.base_artifact import BaseArtifact diff --git a/griptape/common/prompt_stack/contents/image_message_content.py b/griptape/common/prompt_stack/contents/image_message_content.py index 0192a2cb4..335004c30 100644 --- a/griptape/common/prompt_stack/contents/image_message_content.py +++ b/griptape/common/prompt_stack/contents/image_message_content.py @@ -1,11 +1,14 @@ from __future__ import annotations -from collections.abc import Sequence from attrs import define, field -from griptape.artifacts import ImageArtifact from griptape.common import BaseDeltaMessageContent, BaseMessageContent +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact + from collections.abc import Sequence @define diff --git a/griptape/common/prompt_stack/contents/text_message_content.py b/griptape/common/prompt_stack/contents/text_message_content.py index 1d7b2bd5b..b98402097 100644 --- a/griptape/common/prompt_stack/contents/text_message_content.py +++ b/griptape/common/prompt_stack/contents/text_message_content.py @@ -1,10 +1,13 @@ from __future__ import annotations from attrs import define, field -from collections.abc import Sequence from griptape.artifacts import TextArtifact from griptape.common import BaseMessageContent, BaseDeltaMessageContent, TextDeltaMessageContent +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from collections.abc import Sequence @define diff --git a/griptape/common/prompt_stack/messages/base_message.py b/griptape/common/prompt_stack/messages/base_message.py index 3cc8e532a..84de85d7d 100644 --- a/griptape/common/prompt_stack/messages/base_message.py +++ b/griptape/common/prompt_stack/messages/base_message.py @@ -1,13 +1,15 @@ from __future__ import annotations from abc import ABC -from typing import Optional, Union +from typing import Optional, Union, TYPE_CHECKING from attrs import Factory, define, field -from griptape.common import BaseMessageContent, BaseDeltaMessageContent from griptape.mixins import SerializableMixin +if TYPE_CHECKING: + from griptape.common import BaseMessageContent, BaseDeltaMessageContent + @define class BaseMessage(ABC, SerializableMixin): diff --git a/griptape/common/prompt_stack/messages/delta_message.py b/griptape/common/prompt_stack/messages/delta_message.py index a540d205c..b535451db 100644 --- a/griptape/common/prompt_stack/messages/delta_message.py +++ b/griptape/common/prompt_stack/messages/delta_message.py @@ -1,13 +1,15 @@ from __future__ import annotations -from typing import Optional +from typing import Optional, TYPE_CHECKING from attrs import define, field -from griptape.common import BaseDeltaMessageContent from .base_message import BaseMessage +if TYPE_CHECKING: + from griptape.common import BaseDeltaMessageContent + @define class DeltaMessage(BaseMessage): diff --git a/griptape/config/base_structure_config.py b/griptape/config/base_structure_config.py index 0e07d29f5..2ceaf024f 100644 --- a/griptape/config/base_structure_config.py +++ b/griptape/config/base_structure_config.py @@ -1,23 +1,25 @@ from __future__ import annotations from abc import ABC -from typing import Optional +from typing import Optional, TYPE_CHECKING from attrs import define, field from griptape.config import BaseConfig -from griptape.drivers import ( - BaseConversationMemoryDriver, - BaseEmbeddingDriver, - BaseImageGenerationDriver, - BaseImageQueryDriver, - BasePromptDriver, - BaseVectorStoreDriver, - BaseTextToSpeechDriver, - BaseAudioTranscriptionDriver, -) from griptape.utils import dict_merge +if TYPE_CHECKING: + from griptape.drivers import ( + BaseConversationMemoryDriver, + BaseEmbeddingDriver, + BaseImageGenerationDriver, + BaseImageQueryDriver, + BasePromptDriver, + BaseVectorStoreDriver, + BaseTextToSpeechDriver, + BaseAudioTranscriptionDriver, + ) + @define class BaseStructureConfig(BaseConfig, ABC): diff --git a/griptape/drivers/audio_transcription/base_audio_transcription_driver.py b/griptape/drivers/audio_transcription/base_audio_transcription_driver.py index 3cc368c94..2ccf752b7 100644 --- a/griptape/drivers/audio_transcription/base_audio_transcription_driver.py +++ b/griptape/drivers/audio_transcription/base_audio_transcription_driver.py @@ -5,11 +5,11 @@ from attrs import define, field -from griptape.artifacts import TextArtifact, AudioArtifact from griptape.events import StartAudioTranscriptionEvent, FinishAudioTranscriptionEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: + from griptape.artifacts import TextArtifact, AudioArtifact from griptape.structures import Structure diff --git a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py index 903022f86..8a70c98e2 100644 --- a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py @@ -4,10 +4,10 @@ from attrs import define, field, Factory from griptape.drivers import BaseEmbeddingDriver from griptape.tokenizers.amazon_bedrock_tokenizer import AmazonBedrockTokenizer -from griptape.tokenizers.base_tokenizer import BaseTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from griptape.tokenizers.base_tokenizer import BaseTokenizer import boto3 diff --git a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py index b754b0608..d90eefba7 100644 --- a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py @@ -4,10 +4,10 @@ from attrs import define, field, Factory from griptape.drivers import BaseEmbeddingDriver from griptape.tokenizers.amazon_bedrock_tokenizer import AmazonBedrockTokenizer -from griptape.tokenizers.base_tokenizer import BaseTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from griptape.tokenizers.base_tokenizer import BaseTokenizer import boto3 diff --git a/griptape/drivers/embedding/base_embedding_driver.py b/griptape/drivers/embedding/base_embedding_driver.py index 0fcc05fc1..a92fa325a 100644 --- a/griptape/drivers/embedding/base_embedding_driver.py +++ b/griptape/drivers/embedding/base_embedding_driver.py @@ -1,14 +1,16 @@ from __future__ import annotations import numpy as np -from typing import Optional +from typing import Optional, TYPE_CHECKING from abc import ABC, abstractmethod from attrs import define, field -from griptape.artifacts import TextArtifact from griptape.mixins import ExponentialBackoffMixin -from griptape.tokenizers import BaseTokenizer from griptape.chunkers import BaseChunker, TextChunker from griptape.mixins import SerializableMixin +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact + from griptape.tokenizers import BaseTokenizer + @define class BaseEmbeddingDriver(SerializableMixin, ExponentialBackoffMixin, ABC): diff --git a/griptape/drivers/event_listener/base_event_listener_driver.py b/griptape/drivers/event_listener/base_event_listener_driver.py index b433ed755..cc0f9d36c 100644 --- a/griptape/drivers/event_listener/base_event_listener_driver.py +++ b/griptape/drivers/event_listener/base_event_listener_driver.py @@ -2,9 +2,11 @@ from abc import ABC, abstractmethod from concurrent import futures from logging import Logger -from typing import Callable +from typing import Callable, TYPE_CHECKING from attrs import Factory, define, field -from griptape.events import BaseEvent + +if TYPE_CHECKING: + from griptape.events import BaseEvent logger = Logger(__name__) diff --git a/griptape/drivers/image_generation/base_image_generation_driver.py b/griptape/drivers/image_generation/base_image_generation_driver.py index dbe42442f..704595aec 100644 --- a/griptape/drivers/image_generation/base_image_generation_driver.py +++ b/griptape/drivers/image_generation/base_image_generation_driver.py @@ -5,11 +5,11 @@ from attrs import define, field -from griptape.artifacts import ImageArtifact from griptape.events import StartImageGenerationEvent, FinishImageGenerationEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact from griptape.structures import Structure diff --git a/griptape/drivers/image_generation/openai_image_generation_driver.py b/griptape/drivers/image_generation/openai_image_generation_driver.py index abc961e3d..72ce20a92 100644 --- a/griptape/drivers/image_generation/openai_image_generation_driver.py +++ b/griptape/drivers/image_generation/openai_image_generation_driver.py @@ -1,15 +1,17 @@ from __future__ import annotations import base64 -from typing import Literal, Optional, cast, Union +from typing import Literal, Optional, cast, Union, TYPE_CHECKING import openai -from openai.types.images_response import ImagesResponse from attrs import field, Factory, define from griptape.artifacts import ImageArtifact from griptape.drivers import BaseImageGenerationDriver +if TYPE_CHECKING: + from openai.types.images_response import ImagesResponse + @define class OpenAiImageGenerationDriver(BaseImageGenerationDriver): diff --git a/griptape/drivers/image_generation_model/base_image_generation_model_driver.py b/griptape/drivers/image_generation_model/base_image_generation_model_driver.py index 803863319..c5cc6ff2d 100644 --- a/griptape/drivers/image_generation_model/base_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/base_image_generation_model_driver.py @@ -1,13 +1,15 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Any, Optional +from typing import Any, Optional, TYPE_CHECKING from attrs import define -from griptape.artifacts import ImageArtifact from griptape.mixins import SerializableMixin +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact + @define class BaseImageGenerationModelDriver(SerializableMixin, ABC): diff --git a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py index 03d593eac..9be3cc6b9 100644 --- a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py @@ -2,13 +2,15 @@ import base64 import logging -from typing import Optional +from typing import Optional, TYPE_CHECKING from attrs import field, define -from griptape.artifacts import ImageArtifact from griptape.drivers import BaseImageGenerationModelDriver +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact + @define class BedrockStableDiffusionImageGenerationModelDriver(BaseImageGenerationModelDriver): diff --git a/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py b/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py index 2f4577aa7..bfa998c1d 100644 --- a/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py @@ -1,13 +1,15 @@ from __future__ import annotations import base64 -from typing import Any, Optional +from typing import Any, Optional, TYPE_CHECKING from attrs import field, define -from griptape.artifacts import ImageArtifact from griptape.drivers import BaseImageGenerationModelDriver +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact + @define class BedrockTitanImageGenerationModelDriver(BaseImageGenerationModelDriver): diff --git a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py index e91cbbedc..1377bfce9 100644 --- a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py +++ b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py @@ -1,12 +1,12 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any from attrs import define, field, Factory -from griptape.artifacts import ImageArtifact, TextArtifact from griptape.drivers import BaseMultiModelImageQueryDriver from griptape.utils import import_optional_dependency import json if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact, TextArtifact import boto3 diff --git a/griptape/drivers/image_query/base_image_query_driver.py b/griptape/drivers/image_query/base_image_query_driver.py index 8944dd931..44aa13ce2 100644 --- a/griptape/drivers/image_query/base_image_query_driver.py +++ b/griptape/drivers/image_query/base_image_query_driver.py @@ -5,11 +5,11 @@ from attrs import define, field -from griptape.artifacts import TextArtifact, ImageArtifact from griptape.events import StartImageQueryEvent, FinishImageQueryEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: + from griptape.artifacts import TextArtifact, ImageArtifact from griptape.structures import Structure diff --git a/griptape/drivers/image_query_model/base_image_query_model_driver.py b/griptape/drivers/image_query_model/base_image_query_model_driver.py index 746a9f84c..39d858288 100644 --- a/griptape/drivers/image_query_model/base_image_query_model_driver.py +++ b/griptape/drivers/image_query_model/base_image_query_model_driver.py @@ -1,8 +1,11 @@ from __future__ import annotations from abc import ABC, abstractmethod from attrs import define -from griptape.artifacts import TextArtifact, ImageArtifact from griptape.mixins import SerializableMixin +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact, ImageArtifact @define diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 8a1072716..5158740df 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Iterator from typing import TYPE_CHECKING, Any from attrs import Factory, define, field @@ -33,6 +32,7 @@ from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from collections.abc import Iterator import boto3 from griptape.common import PromptStack diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index dacaa62b0..08ec3a3fa 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -1,7 +1,6 @@ from __future__ import annotations import json -from collections.abc import Iterator from typing import TYPE_CHECKING, Any, Optional from attrs import Factory, define, field @@ -13,6 +12,7 @@ from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from collections.abc import Iterator import boto3 from griptape.common import PromptStack diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 21fdc841c..5ef28e143 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Iterator from typing import TYPE_CHECKING, Optional from attrs import Factory, define, field @@ -34,6 +33,7 @@ from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from collections.abc import Iterator from anthropic import Client from anthropic.types import ContentBlock, ContentBlockDeltaEvent, ContentBlockStartEvent diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index ea785d045..e36654b23 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -1,7 +1,6 @@ from __future__ import annotations from abc import ABC, abstractmethod -from collections.abc import Iterator from typing import TYPE_CHECKING, Optional from attrs import Factory, define, field @@ -18,9 +17,10 @@ ) from griptape.events import CompletionChunkEvent, FinishPromptEvent, StartPromptEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin -from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: + from griptape.tokenizers import BaseTokenizer + from collections.abc import Iterator from griptape.structures import Structure diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index a07489005..b2cc6ea83 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -1,6 +1,5 @@ from __future__ import annotations from typing import TYPE_CHECKING, Any -from collections.abc import Iterator from attrs import define, field, Factory from griptape.artifacts import TextArtifact from griptape.artifacts.list_artifact import ListArtifact @@ -24,6 +23,7 @@ from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: + from collections.abc import Iterator from cohere import Client from cohere.types import NonStreamedChatResponse from griptape.tools import BaseTool diff --git a/griptape/drivers/prompt/dummy_prompt_driver.py b/griptape/drivers/prompt/dummy_prompt_driver.py index 72757624d..301474954 100644 --- a/griptape/drivers/prompt/dummy_prompt_driver.py +++ b/griptape/drivers/prompt/dummy_prompt_driver.py @@ -1,12 +1,15 @@ from __future__ import annotations -from collections.abc import Iterator from attrs import Factory, define, field -from griptape.common import PromptStack, Message, DeltaMessage from griptape.drivers import BasePromptDriver from griptape.exceptions import DummyException from griptape.tokenizers import DummyTokenizer +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.common import PromptStack, Message, DeltaMessage + from collections.abc import Iterator @define diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 41be786b6..c1ef91ec8 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -1,11 +1,9 @@ from __future__ import annotations import json -from collections.abc import Iterator from typing import TYPE_CHECKING, Optional from attrs import Factory, define, field -from google.generativeai.types import ContentsType from griptape.common import ( @@ -29,6 +27,8 @@ from schema import Schema if TYPE_CHECKING: + from google.generativeai.types import ContentsType + from collections.abc import Iterator from google.generativeai import GenerativeModel from google.generativeai.types import ContentDict, GenerateContentResponse from google.generativeai.protos import Part diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index f327010c4..ae080e34b 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Iterator from typing import TYPE_CHECKING from attrs import Factory, define, field @@ -11,6 +10,7 @@ from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from collections.abc import Iterator from huggingface_hub import InferenceClient diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index 6dabc3e20..cd77deefe 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Iterator from typing import TYPE_CHECKING from attrs import Factory, define, field @@ -12,6 +11,7 @@ from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from collections.abc import Iterator from transformers import TextGenerationPipeline diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py index 5a78abf29..d554b7c96 100644 --- a/griptape/drivers/prompt/ollama_prompt_driver.py +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -4,7 +4,6 @@ from attrs import define, field, Factory from griptape.artifacts import TextArtifact from griptape.drivers import BasePromptDriver -from griptape.tokenizers.base_tokenizer import BaseTokenizer from griptape.common import PromptStack, TextMessageContent from griptape.utils import import_optional_dependency from griptape.tokenizers import SimpleTokenizer @@ -12,6 +11,7 @@ from griptape.common import ImageMessageContent if TYPE_CHECKING: + from griptape.tokenizers.base_tokenizer import BaseTokenizer from ollama import Client diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index d1456007e..755e05f56 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -1,7 +1,6 @@ from __future__ import annotations import json -from collections.abc import Iterator from typing import TYPE_CHECKING, Literal, Optional import openai @@ -27,6 +26,7 @@ from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer if TYPE_CHECKING: + from collections.abc import Iterator from openai.types.chat.chat_completion_chunk import ChoiceDelta from openai.types.chat.chat_completion_message import ChatCompletionMessage diff --git a/griptape/drivers/rerank/cohere_rerank_driver.py b/griptape/drivers/rerank/cohere_rerank_driver.py index 57a7863d4..6475ba766 100644 --- a/griptape/drivers/rerank/cohere_rerank_driver.py +++ b/griptape/drivers/rerank/cohere_rerank_driver.py @@ -1,11 +1,11 @@ from __future__ import annotations from typing import TYPE_CHECKING, Optional from attrs import define, field, Factory -from griptape.artifacts import TextArtifact from griptape.drivers import BaseRerankDriver from griptape.utils import import_optional_dependency if TYPE_CHECKING: + from griptape.artifacts import TextArtifact from cohere import Client diff --git a/griptape/drivers/text_to_speech/base_text_to_speech_driver.py b/griptape/drivers/text_to_speech/base_text_to_speech_driver.py index 4f6dbcf25..d91347c19 100644 --- a/griptape/drivers/text_to_speech/base_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/base_text_to_speech_driver.py @@ -5,12 +5,12 @@ from attrs import define, field -from griptape.artifacts.audio_artifact import AudioArtifact from griptape.events.finish_text_to_speech_event import FinishTextToSpeechEvent from griptape.events.start_text_to_speech_event import StartTextToSpeechEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: + from griptape.artifacts.audio_artifact import AudioArtifact from griptape.structures import Structure diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 2957d7557..98c078fd6 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -4,13 +4,15 @@ from concurrent import futures from dataclasses import dataclass from typing import Any, Callable -from typing import Optional +from typing import Optional, TYPE_CHECKING from attrs import define, field, Factory from griptape import utils from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact -from griptape.drivers import BaseEmbeddingDriver from griptape.mixins import SerializableMixin +if TYPE_CHECKING: + from griptape.drivers import BaseEmbeddingDriver + @define class BaseVectorStoreDriver(SerializableMixin, ABC): diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index f20530cff..a46f4b02f 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -3,10 +3,10 @@ from griptape import utils from griptape.utils import import_optional_dependency from griptape.drivers import BaseVectorStoreDriver -from griptape.artifacts import TextArtifact from attrs import define, field, Factory if TYPE_CHECKING: + from griptape.artifacts import TextArtifact import marqo diff --git a/griptape/engines/audio/text_to_speech_engine.py b/griptape/engines/audio/text_to_speech_engine.py index 634837d82..d707c5099 100644 --- a/griptape/engines/audio/text_to_speech_engine.py +++ b/griptape/engines/audio/text_to_speech_engine.py @@ -2,8 +2,11 @@ from attrs import define, field -from griptape.artifacts.audio_artifact import AudioArtifact -from griptape.drivers import BaseTextToSpeechDriver +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.drivers import BaseTextToSpeechDriver + from griptape.artifacts.audio_artifact import AudioArtifact @define diff --git a/griptape/engines/extraction/base_extraction_engine.py b/griptape/engines/extraction/base_extraction_engine.py index e8bd29129..aae56569e 100644 --- a/griptape/engines/extraction/base_extraction_engine.py +++ b/griptape/engines/extraction/base_extraction_engine.py @@ -1,11 +1,13 @@ from __future__ import annotations -from typing import Optional +from typing import Optional, TYPE_CHECKING from abc import ABC, abstractmethod from attrs import define, field, Factory -from griptape.artifacts import ListArtifact, ErrorArtifact from griptape.chunkers import BaseChunker, TextChunker -from griptape.drivers import BasePromptDriver -from griptape.rules import Ruleset + +if TYPE_CHECKING: + from griptape.artifacts import ListArtifact, ErrorArtifact + from griptape.rules import Ruleset + from griptape.drivers import BasePromptDriver @define diff --git a/griptape/engines/extraction/csv_extraction_engine.py b/griptape/engines/extraction/csv_extraction_engine.py index 6fe9bb879..c85d26de2 100644 --- a/griptape/engines/extraction/csv_extraction_engine.py +++ b/griptape/engines/extraction/csv_extraction_engine.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import Optional, cast +from typing import Optional, cast, TYPE_CHECKING import csv import io from attrs import field, Factory, define @@ -8,7 +8,9 @@ from griptape.common.prompt_stack.messages.message import Message from griptape.engines import BaseExtractionEngine from griptape.utils import J2 -from griptape.rules import Ruleset + +if TYPE_CHECKING: + from griptape.rules import Ruleset @define diff --git a/griptape/engines/extraction/json_extraction_engine.py b/griptape/engines/extraction/json_extraction_engine.py index 830092dab..13f6f58bb 100644 --- a/griptape/engines/extraction/json_extraction_engine.py +++ b/griptape/engines/extraction/json_extraction_engine.py @@ -1,5 +1,5 @@ from __future__ import annotations -from typing import Optional, cast +from typing import Optional, cast, TYPE_CHECKING import json from attrs import field, Factory, define from griptape.artifacts import TextArtifact, ListArtifact, ErrorArtifact @@ -7,7 +7,9 @@ from griptape.engines import BaseExtractionEngine from griptape.utils import J2 from griptape.common import PromptStack -from griptape.rules import Ruleset + +if TYPE_CHECKING: + from griptape.rules import Ruleset @define diff --git a/griptape/engines/image/base_image_generation_engine.py b/griptape/engines/image/base_image_generation_engine.py index 2c65c1a60..5fcf45544 100644 --- a/griptape/engines/image/base_image_generation_engine.py +++ b/griptape/engines/image/base_image_generation_engine.py @@ -2,11 +2,13 @@ from abc import ABC, abstractmethod from attrs import field, define -from typing import Optional +from typing import Optional, TYPE_CHECKING -from griptape.artifacts import ImageArtifact -from griptape.drivers import BaseImageGenerationDriver -from griptape.rules import Ruleset + +if TYPE_CHECKING: + from griptape.drivers import BaseImageGenerationDriver + from griptape.artifacts import ImageArtifact + from griptape.rules import Ruleset @define diff --git a/griptape/engines/image/inpainting_image_generation_engine.py b/griptape/engines/image/inpainting_image_generation_engine.py index 7fb83d66f..527cb4eb6 100644 --- a/griptape/engines/image/inpainting_image_generation_engine.py +++ b/griptape/engines/image/inpainting_image_generation_engine.py @@ -1,11 +1,13 @@ from __future__ import annotations from attrs import define -from typing import Optional +from typing import Optional, TYPE_CHECKING from griptape.engines import BaseImageGenerationEngine -from griptape.artifacts import ImageArtifact -from griptape.rules import Ruleset + +if TYPE_CHECKING: + from griptape.rules import Ruleset + from griptape.artifacts import ImageArtifact @define diff --git a/griptape/engines/image/outpainting_image_generation_engine.py b/griptape/engines/image/outpainting_image_generation_engine.py index 135e3c77d..46feed614 100644 --- a/griptape/engines/image/outpainting_image_generation_engine.py +++ b/griptape/engines/image/outpainting_image_generation_engine.py @@ -1,12 +1,14 @@ from __future__ import annotations from attrs import define -from typing import Optional +from typing import Optional, TYPE_CHECKING -from griptape.artifacts import ImageArtifact -from griptape.rules import Ruleset from griptape.engines import BaseImageGenerationEngine +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact + from griptape.rules import Ruleset + @define class OutpaintingImageGenerationEngine(BaseImageGenerationEngine): diff --git a/griptape/engines/image/prompt_image_generation_engine.py b/griptape/engines/image/prompt_image_generation_engine.py index 4b4a9ce63..d58ab74b9 100644 --- a/griptape/engines/image/prompt_image_generation_engine.py +++ b/griptape/engines/image/prompt_image_generation_engine.py @@ -1,12 +1,14 @@ from __future__ import annotations from attrs import define -from typing import Optional +from typing import Optional, TYPE_CHECKING -from griptape.rules import Ruleset -from griptape.artifacts import ImageArtifact from griptape.engines import BaseImageGenerationEngine +if TYPE_CHECKING: + from griptape.rules import Ruleset + from griptape.artifacts import ImageArtifact + @define class PromptImageGenerationEngine(BaseImageGenerationEngine): diff --git a/griptape/engines/image/variation_image_generation_engine.py b/griptape/engines/image/variation_image_generation_engine.py index 7b932ac2a..89dfadda1 100644 --- a/griptape/engines/image/variation_image_generation_engine.py +++ b/griptape/engines/image/variation_image_generation_engine.py @@ -2,10 +2,12 @@ from attrs import define -from typing import Optional +from typing import Optional, TYPE_CHECKING from griptape.engines import BaseImageGenerationEngine -from griptape.artifacts import ImageArtifact -from griptape.rules import Ruleset + +if TYPE_CHECKING: + from griptape.rules import Ruleset + from griptape.artifacts import ImageArtifact @define diff --git a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py index a37910da6..248f69af2 100644 --- a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py @@ -1,13 +1,14 @@ from __future__ import annotations import uuid -from typing import TYPE_CHECKING, Sequence, Any, Callable +from typing import TYPE_CHECKING, Any, Callable from attrs import define, field, Factory from griptape import utils from griptape.artifacts import TextArtifact, ErrorArtifact -from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRetrievalRagModule if TYPE_CHECKING: + from collections.abc import Sequence + from griptape.engines.rag import RagContext from griptape.drivers import BaseVectorStoreDriver from griptape.loaders import BaseTextLoader diff --git a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py index 96d249693..00d709346 100644 --- a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py @@ -1,12 +1,13 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Sequence, Any, Callable +from typing import TYPE_CHECKING, Any, Callable from attrs import define, field, Factory from griptape import utils -from griptape.artifacts import TextArtifact -from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRetrievalRagModule if TYPE_CHECKING: + from collections.abc import Sequence + from griptape.engines.rag import RagContext + from griptape.artifacts import TextArtifact from griptape.drivers import BaseVectorStoreDriver diff --git a/griptape/engines/rag/rag_context.py b/griptape/engines/rag/rag_context.py index c0658ad7b..e6f111279 100644 --- a/griptape/engines/rag/rag_context.py +++ b/griptape/engines/rag/rag_context.py @@ -3,10 +3,10 @@ from attrs import define, field from griptape import utils -from griptape.common import Reference from griptape.mixins import SerializableMixin if TYPE_CHECKING: + from griptape.common import Reference from griptape.artifacts import TextArtifact, BaseArtifact diff --git a/griptape/events/base_actions_subtask_event.py b/griptape/events/base_actions_subtask_event.py index 8e1853b1c..cfd900000 100644 --- a/griptape/events/base_actions_subtask_event.py +++ b/griptape/events/base_actions_subtask_event.py @@ -5,7 +5,7 @@ from .base_task_event import BaseTaskEvent if TYPE_CHECKING: - from griptape.tasks import BaseTask, ActionsSubtask + from griptape.tasks import BaseTask @define @@ -16,6 +16,8 @@ class BaseActionsSubtaskEvent(BaseTaskEvent, ABC): @classmethod def from_task(cls, task: BaseTask) -> BaseActionsSubtaskEvent: + from griptape.tasks import ActionsSubtask + if not isinstance(task, ActionsSubtask): raise ValueError("Event must be of instance ActionSubtask.") return cls( diff --git a/griptape/events/base_task_event.py b/griptape/events/base_task_event.py index e853114d5..c486d3f75 100644 --- a/griptape/events/base_task_event.py +++ b/griptape/events/base_task_event.py @@ -1,10 +1,12 @@ from __future__ import annotations from attrs import define, field from abc import ABC -from typing import Optional -from griptape.artifacts import BaseArtifact +from typing import Optional, TYPE_CHECKING from .base_event import BaseEvent +if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact + @define class BaseTaskEvent(BaseEvent, ABC): diff --git a/griptape/events/event_listener.py b/griptape/events/event_listener.py index 44d7b2d85..1aad6ffc5 100644 --- a/griptape/events/event_listener.py +++ b/griptape/events/event_listener.py @@ -1,9 +1,9 @@ from __future__ import annotations from typing import Optional, TYPE_CHECKING, Callable from attrs import define, field, Factory -from .base_event import BaseEvent if TYPE_CHECKING: + from .base_event import BaseEvent from griptape.drivers import BaseEventListenerDriver diff --git a/griptape/loaders/base_loader.py b/griptape/loaders/base_loader.py index 00fbf07ec..d2448d103 100644 --- a/griptape/loaders/base_loader.py +++ b/griptape/loaders/base_loader.py @@ -2,15 +2,17 @@ from abc import ABC, abstractmethod from concurrent import futures -from typing import Any, Optional, Callable -from collections.abc import Mapping, Sequence +from typing import Any, Optional, Callable, TYPE_CHECKING from attrs import define, field, Factory -from griptape.artifacts import BaseArtifact from griptape.utils.futures import execute_futures_dict from griptape.utils.hash import bytes_to_hash, str_to_hash +if TYPE_CHECKING: + from collections.abc import Mapping, Sequence + from griptape.artifacts import BaseArtifact + @define class BaseLoader(ABC): diff --git a/griptape/loaders/base_text_loader.py b/griptape/loaders/base_text_loader.py index 4f2a93183..58787c881 100644 --- a/griptape/loaders/base_text_loader.py +++ b/griptape/loaders/base_text_loader.py @@ -1,15 +1,17 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Any, Optional, Union, cast +from typing import Any, Optional, Union, cast, TYPE_CHECKING from attrs import define, field, Factory from griptape.artifacts import TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact from griptape.chunkers import TextChunker, BaseChunker -from griptape.common import Reference -from griptape.drivers import BaseEmbeddingDriver from griptape.loaders import BaseLoader from griptape.tokenizers import OpenAiTokenizer +if TYPE_CHECKING: + from griptape.common import Reference + from griptape.drivers import BaseEmbeddingDriver + @define class BaseTextLoader(BaseLoader, ABC): diff --git a/griptape/loaders/csv_loader.py b/griptape/loaders/csv_loader.py index d396f80bc..21ca1f5a6 100644 --- a/griptape/loaders/csv_loader.py +++ b/griptape/loaders/csv_loader.py @@ -1,14 +1,16 @@ from __future__ import annotations import csv from io import StringIO -from typing import Optional, Union, cast +from typing import Optional, Union, cast, TYPE_CHECKING from attrs import define, field from griptape.artifacts import CsvRowArtifact, ErrorArtifact -from griptape.drivers import BaseEmbeddingDriver from griptape.loaders import BaseLoader +if TYPE_CHECKING: + from griptape.drivers import BaseEmbeddingDriver + @define class CsvLoader(BaseLoader): diff --git a/griptape/loaders/dataframe_loader.py b/griptape/loaders/dataframe_loader.py index 3d5a0f48b..a547ab7cc 100644 --- a/griptape/loaders/dataframe_loader.py +++ b/griptape/loaders/dataframe_loader.py @@ -5,12 +5,12 @@ from attrs import define, field from griptape.artifacts import CsvRowArtifact -from griptape.drivers import BaseEmbeddingDriver from griptape.loaders import BaseLoader from griptape.utils import import_optional_dependency from griptape.utils.hash import str_to_hash if TYPE_CHECKING: + from griptape.drivers import BaseEmbeddingDriver from pandas import DataFrame diff --git a/griptape/loaders/text_loader.py b/griptape/loaders/text_loader.py index e8a80fa64..2dfa3bbe9 100644 --- a/griptape/loaders/text_loader.py +++ b/griptape/loaders/text_loader.py @@ -1,16 +1,18 @@ from __future__ import annotations -from typing import Optional, Union, cast +from typing import Optional, Union, cast, TYPE_CHECKING from attrs import field, define, Factory from griptape.artifacts import TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact from griptape.chunkers import TextChunker -from griptape.drivers import BaseEmbeddingDriver from griptape.loaders import BaseTextLoader from griptape.tokenizers import OpenAiTokenizer +if TYPE_CHECKING: + from griptape.drivers import BaseEmbeddingDriver + @define class TextLoader(BaseTextLoader): diff --git a/griptape/loaders/web_loader.py b/griptape/loaders/web_loader.py index 64a52b65f..bde2ec305 100644 --- a/griptape/loaders/web_loader.py +++ b/griptape/loaders/web_loader.py @@ -2,8 +2,11 @@ from attrs import define, field, Factory from griptape.artifacts.error_artifact import ErrorArtifact from griptape.drivers import BaseWebScraperDriver, TrafilaturaWebScraperDriver -from griptape.artifacts import TextArtifact from griptape.loaders import BaseTextLoader +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact @define diff --git a/griptape/memory/structure/base_conversation_memory.py b/griptape/memory/structure/base_conversation_memory.py index a8133d64b..e68939026 100644 --- a/griptape/memory/structure/base_conversation_memory.py +++ b/griptape/memory/structure/base_conversation_memory.py @@ -1,12 +1,12 @@ from __future__ import annotations from typing import TYPE_CHECKING, Optional from attrs import define, field -from griptape.memory.structure import Run from griptape.common import PromptStack from griptape.mixins import SerializableMixin from abc import ABC, abstractmethod if TYPE_CHECKING: + from griptape.memory.structure import Run from griptape.drivers import BaseConversationMemoryDriver from griptape.structures import Structure diff --git a/griptape/memory/task/storage/base_artifact_storage.py b/griptape/memory/task/storage/base_artifact_storage.py index e8378fee4..e6ec68797 100644 --- a/griptape/memory/task/storage/base_artifact_storage.py +++ b/griptape/memory/task/storage/base_artifact_storage.py @@ -1,8 +1,10 @@ from __future__ import annotations -from typing import Any +from typing import Any, TYPE_CHECKING from abc import ABC, abstractmethod from attrs import define -from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact, InfoArtifact + +if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact, InfoArtifact @define diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 0d135bcbd..51994fa6c 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -2,11 +2,11 @@ from typing import TYPE_CHECKING, Any, Optional from attrs import define, field from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact, InfoArtifact -from griptape.drivers import BaseVectorStoreDriver from griptape.engines.rag import RagEngine, RagContext from griptape.memory.task.storage import BaseArtifactStorage if TYPE_CHECKING: + from griptape.drivers import BaseVectorStoreDriver from griptape.engines import BaseSummaryEngine, CsvExtractionEngine, JsonExtractionEngine diff --git a/griptape/mixins/serializable_mixin.py b/griptape/mixins/serializable_mixin.py index 667ae752d..5535c69c6 100644 --- a/griptape/mixins/serializable_mixin.py +++ b/griptape/mixins/serializable_mixin.py @@ -1,15 +1,17 @@ from __future__ import annotations import json -from typing import TypeVar, Generic, cast, Optional +from typing import TypeVar, Generic, cast, Optional, TYPE_CHECKING from attrs import Factory, define, field from abc import ABC -from marshmallow import Schema from griptape.schemas.base_schema import BaseSchema from importlib import import_module +if TYPE_CHECKING: + from marshmallow import Schema + T = TypeVar("T", bound="SerializableMixin") diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 867486700..cfc9c2f5c 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -103,11 +103,28 @@ def _resolve_types(cls, attrs_cls: type) -> None: from griptape.utils.import_utils import import_optional_dependency, is_dependency_installed # These modules are required to avoid `NameError`s when resolving types. - from griptape.drivers import BaseConversationMemoryDriver, BasePromptDriver + from griptape.drivers import ( + BaseConversationMemoryDriver, + BasePromptDriver, + BaseImageGenerationDriver, + BaseImageQueryDriver, + BaseEmbeddingDriver, + BaseVectorStoreDriver, + BaseTextToSpeechDriver, + BaseAudioTranscriptionDriver, + ) from griptape.structures import Structure - from griptape.common import PromptStack, Message, Reference, ToolAction + from griptape.common import ( + PromptStack, + Message, + Reference, + ToolAction, + BaseMessageContent, + BaseDeltaMessageContent, + ) from griptape.tokenizers.base_tokenizer import BaseTokenizer from griptape.tools import BaseTool + from griptape.memory.structure import Run from typing import Any from griptape.artifacts import BaseArtifact @@ -122,19 +139,29 @@ def _resolve_types(cls, attrs_cls: type) -> None: attrs.resolve_types( attrs_cls, localns={ + "BasePromptDriver": BasePromptDriver, + "BaseImageQueryDriver": BaseImageQueryDriver, + "BaseEmbeddingDriver": BaseEmbeddingDriver, + "BaseVectorStoreDriver": BaseVectorStoreDriver, + "BaseTextToSpeechDriver": BaseTextToSpeechDriver, + "BaseAudioTranscriptionDriver": BaseAudioTranscriptionDriver, + "BaseConversationMemoryDriver": BaseConversationMemoryDriver, + "BaseImageGenerationDriver": BaseImageGenerationDriver, + "BaseArtifact": BaseArtifact, "PromptStack": PromptStack, - "Usage": Message.Usage, + "BaseMessageContent": BaseMessageContent, + "BaseDeltaMessageContent": BaseDeltaMessageContent, "BaseTool": BaseTool, + "Usage": Message.Usage, "Structure": Structure, - "BaseConversationMemoryDriver": BaseConversationMemoryDriver, - "BasePromptDriver": BasePromptDriver, "BaseTokenizer": BaseTokenizer, - "boto3": boto3, - "Client": Client, "ToolAction": ToolAction, - "GenerativeModel": GenerativeModel, "Reference": Reference, - "BaseArtifact": BaseArtifact, + "Run": Run, + # Third party modules + "Client": Client, + "GenerativeModel": GenerativeModel, + "boto3": boto3, }, ) diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 598aae37c..1df541e2a 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -2,13 +2,13 @@ from typing import TYPE_CHECKING, Optional, Callable from attrs import define, field from griptape.artifacts.text_artifact import TextArtifact -from griptape.tools import BaseTool from griptape.memory.structure import Run from griptape.structures import Structure from griptape.tasks import PromptTask, ToolkitTask -from griptape.artifacts import BaseArtifact if TYPE_CHECKING: + from griptape.tools import BaseTool + from griptape.artifacts import BaseArtifact from griptape.tasks import BaseTask diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index c7b779590..52098f05f 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -19,18 +19,18 @@ MetadataBeforeResponseRagModule, ) from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage -from griptape.events import BaseEvent, EventListener from griptape.events.finish_structure_run_event import FinishStructureRunEvent from griptape.events.start_structure_run_event import StartStructureRunEvent from griptape.memory import TaskMemory from griptape.memory.meta import MetaMemory from griptape.memory.structure import ConversationMemory from griptape.memory.task.storage import BlobArtifactStorage, TextArtifactStorage -from griptape.rules import Rule, Ruleset -from griptape.tasks import BaseTask from griptape.utils import deprecation_warn if TYPE_CHECKING: + from griptape.rules import Rule, Ruleset + from griptape.events import BaseEvent, EventListener + from griptape.tasks import BaseTask from griptape.memory.structure import BaseConversationMemory diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index f7bc2e893..ffb3bf721 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -1,13 +1,15 @@ from __future__ import annotations import concurrent.futures as futures from graphlib import TopologicalSorter -from typing import Any, Optional, Callable +from typing import Any, Optional, Callable, TYPE_CHECKING from attrs import define, field, Factory from griptape.artifacts import ErrorArtifact from griptape.structures import Structure -from griptape.tasks import BaseTask from griptape.memory.structure import Run +if TYPE_CHECKING: + from griptape.tasks import BaseTask + @define class Workflow(Structure): diff --git a/griptape/tasks/audio_transcription_task.py b/griptape/tasks/audio_transcription_task.py index 57dbf6782..607911782 100644 --- a/griptape/tasks/audio_transcription_task.py +++ b/griptape/tasks/audio_transcription_task.py @@ -3,8 +3,11 @@ from attrs import define, field from griptape.engines import AudioTranscriptionEngine -from griptape.artifacts import TextArtifact from griptape.tasks.base_audio_input_task import BaseAudioInputTask +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact @define diff --git a/griptape/tasks/base_image_generation_task.py b/griptape/tasks/base_image_generation_task.py index 75f57b711..3b8cfb16a 100644 --- a/griptape/tasks/base_image_generation_task.py +++ b/griptape/tasks/base_image_generation_task.py @@ -5,11 +5,14 @@ from attrs import field, define -from griptape.artifacts import MediaArtifact from griptape.loaders import ImageLoader from griptape.mixins import RuleMixin, BlobArtifactFileOutputMixin from griptape.rules import Ruleset, Rule from griptape.tasks import BaseTask +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.artifacts import MediaArtifact @define diff --git a/griptape/tasks/extraction_task.py b/griptape/tasks/extraction_task.py index 03838ef6c..8c9ac85b1 100644 --- a/griptape/tasks/extraction_task.py +++ b/griptape/tasks/extraction_task.py @@ -1,8 +1,11 @@ from __future__ import annotations from attrs import define, field -from griptape.artifacts import ListArtifact, ErrorArtifact -from griptape.engines import BaseExtractionEngine from griptape.tasks import BaseTextInputTask +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.engines import BaseExtractionEngine + from griptape.artifacts import ListArtifact, ErrorArtifact @define diff --git a/griptape/tasks/rag_task.py b/griptape/tasks/rag_task.py index e85c8f28a..fd5c5daa1 100644 --- a/griptape/tasks/rag_task.py +++ b/griptape/tasks/rag_task.py @@ -1,8 +1,11 @@ from __future__ import annotations from attrs import define, field from griptape.artifacts import ErrorArtifact, BaseArtifact -from griptape.engines.rag import RagEngine from griptape.tasks import BaseTextInputTask +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.engines.rag import RagEngine @define diff --git a/griptape/tasks/structure_run_task.py b/griptape/tasks/structure_run_task.py index 012f5c235..148b5b2de 100644 --- a/griptape/tasks/structure_run_task.py +++ b/griptape/tasks/structure_run_task.py @@ -3,9 +3,12 @@ from attrs import define, field -from griptape.artifacts import BaseArtifact -from griptape.drivers.structure_run.base_structure_run_driver import BaseStructureRunDriver from griptape.tasks import BaseMultiTextInputTask +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.drivers.structure_run.base_structure_run_driver import BaseStructureRunDriver + from griptape.artifacts import BaseArtifact @define diff --git a/griptape/tasks/text_to_speech_task.py b/griptape/tasks/text_to_speech_task.py index d69e907b1..29a2f0165 100644 --- a/griptape/tasks/text_to_speech_task.py +++ b/griptape/tasks/text_to_speech_task.py @@ -1,16 +1,18 @@ from __future__ import annotations -from typing import Callable +from typing import Callable, TYPE_CHECKING from attrs import define, field -from griptape.artifacts.audio_artifact import AudioArtifact from griptape.engines import TextToSpeechEngine from griptape.artifacts import TextArtifact -from griptape.tasks import BaseTask from griptape.tasks.base_audio_generation_task import BaseAudioGenerationTask from griptape.utils import J2 +if TYPE_CHECKING: + from griptape.artifacts.audio_artifact import AudioArtifact + from griptape.tasks import BaseTask + @define class TextToSpeechTask(BaseAudioGenerationTask): diff --git a/griptape/tasks/tool_task.py b/griptape/tasks/tool_task.py index da40fd31a..447525f3e 100644 --- a/griptape/tasks/tool_task.py +++ b/griptape/tasks/tool_task.py @@ -3,17 +3,17 @@ import re from typing import Optional, TYPE_CHECKING from attrs import define, field -from schema import Schema from griptape import utils from griptape.artifacts import InfoArtifact, BaseArtifact, ErrorArtifact, ListArtifact from griptape.tasks import PromptTask, ActionsSubtask -from griptape.tools import BaseTool from griptape.utils import J2 from griptape.mixins import ActionsSubtaskOriginMixin -from griptape.common import PromptStack if TYPE_CHECKING: + from schema import Schema + from griptape.tools import BaseTool + from griptape.common import PromptStack from griptape.memory import TaskMemory from griptape.structures import Structure diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index 0c5dce67c..97835928c 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -2,7 +2,6 @@ import json from typing import TYPE_CHECKING, Callable, Optional from attrs import define, field, Factory -from schema import Schema from griptape import utils from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact, ListArtifact, ActionArtifact @@ -13,6 +12,7 @@ from griptape.common import PromptStack, ToolAction if TYPE_CHECKING: + from schema import Schema from griptape.tools import BaseTool from griptape.memory import TaskMemory from griptape.structures import Structure diff --git a/griptape/tools/audio_transcription_client/tool.py b/griptape/tools/audio_transcription_client/tool.py index ad0f0626e..3fdde0102 100644 --- a/griptape/tools/audio_transcription_client/tool.py +++ b/griptape/tools/audio_transcription_client/tool.py @@ -1,17 +1,19 @@ from __future__ import annotations -from typing import Any, cast +from typing import Any, cast, TYPE_CHECKING from attrs import define, field, Factory from schema import Schema, Literal from griptape.artifacts import ErrorArtifact, AudioArtifact, TextArtifact -from griptape.engines import AudioTranscriptionEngine from griptape.loaders.audio_loader import AudioLoader from griptape.tools import BaseTool from griptape.utils import load_artifact_from_memory from griptape.utils.decorators import activity +if TYPE_CHECKING: + from griptape.engines import AudioTranscriptionEngine + @define class AudioTranscriptionClient(BaseTool): diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 44db36f2a..c46027049 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -11,10 +11,10 @@ import yaml from attrs import define, field, Factory from griptape.artifacts import BaseArtifact, InfoArtifact, TextArtifact -from griptape.common import ToolAction from griptape.mixins import ActivityMixin if TYPE_CHECKING: + from griptape.common import ToolAction from griptape.memory import TaskMemory from griptape.tasks import ActionsSubtask diff --git a/griptape/tools/image_query_client/tool.py b/griptape/tools/image_query_client/tool.py index 60f2970ff..b03f3fed0 100644 --- a/griptape/tools/image_query_client/tool.py +++ b/griptape/tools/image_query_client/tool.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any, cast +from typing import Any, cast, TYPE_CHECKING from attrs import define, field, Factory from schema import Schema, Literal @@ -10,7 +10,9 @@ from griptape.tools import BaseTool from griptape.utils import load_artifact_from_memory from griptape.utils.decorators import activity -from griptape.engines import ImageQueryEngine + +if TYPE_CHECKING: + from griptape.engines import ImageQueryEngine @define diff --git a/griptape/tools/inpainting_image_generation_client/tool.py b/griptape/tools/inpainting_image_generation_client/tool.py index 02799ad29..c343f9923 100644 --- a/griptape/tools/inpainting_image_generation_client/tool.py +++ b/griptape/tools/inpainting_image_generation_client/tool.py @@ -1,18 +1,20 @@ from __future__ import annotations -from typing import Any, cast +from typing import Any, cast, TYPE_CHECKING from attrs import define, field from schema import Schema, Literal from griptape.artifacts import ErrorArtifact, ImageArtifact -from griptape.engines import InpaintingImageGenerationEngine from griptape.loaders import ImageLoader from griptape.mixins import BlobArtifactFileOutputMixin from griptape.tools import BaseTool from griptape.utils.decorators import activity from griptape.utils.load_artifact_from_memory import load_artifact_from_memory +if TYPE_CHECKING: + from griptape.engines import InpaintingImageGenerationEngine + @define class InpaintingImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): diff --git a/griptape/tools/outpainting_image_generation_client/tool.py b/griptape/tools/outpainting_image_generation_client/tool.py index bd9a2125c..72db0e54c 100644 --- a/griptape/tools/outpainting_image_generation_client/tool.py +++ b/griptape/tools/outpainting_image_generation_client/tool.py @@ -1,18 +1,20 @@ from __future__ import annotations -from typing import Any, cast +from typing import Any, cast, TYPE_CHECKING from attrs import define, field from schema import Schema, Literal from griptape.artifacts import ErrorArtifact, ImageArtifact -from griptape.engines import OutpaintingImageGenerationEngine from griptape.loaders import ImageLoader from griptape.tools import BaseTool from griptape.utils.decorators import activity from griptape.mixins import BlobArtifactFileOutputMixin from griptape.utils.load_artifact_from_memory import load_artifact_from_memory +if TYPE_CHECKING: + from griptape.engines import OutpaintingImageGenerationEngine + @define class OutpaintingImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): diff --git a/griptape/tools/prompt_image_generation_client/tool.py b/griptape/tools/prompt_image_generation_client/tool.py index 6f4ce0e1f..799df8673 100644 --- a/griptape/tools/prompt_image_generation_client/tool.py +++ b/griptape/tools/prompt_image_generation_client/tool.py @@ -3,11 +3,14 @@ from attrs import define, field from schema import Schema, Literal -from griptape.artifacts import ErrorArtifact, ImageArtifact -from griptape.engines import PromptImageGenerationEngine from griptape.tools import BaseTool from griptape.utils.decorators import activity from griptape.mixins import BlobArtifactFileOutputMixin +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.engines import PromptImageGenerationEngine + from griptape.artifacts import ErrorArtifact, ImageArtifact @define diff --git a/griptape/tools/rag_client/tool.py b/griptape/tools/rag_client/tool.py index 94422cc15..034843798 100644 --- a/griptape/tools/rag_client/tool.py +++ b/griptape/tools/rag_client/tool.py @@ -2,9 +2,12 @@ from attrs import define, field from schema import Schema, Literal from griptape.artifacts import ErrorArtifact, BaseArtifact -from griptape.engines.rag import RagEngine from griptape.tools import BaseTool from griptape.utils.decorators import activity +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.engines.rag import RagEngine @define(kw_only=True) diff --git a/griptape/tools/sql_client/tool.py b/griptape/tools/sql_client/tool.py index a07c2e734..c06cfe4d9 100644 --- a/griptape/tools/sql_client/tool.py +++ b/griptape/tools/sql_client/tool.py @@ -1,12 +1,14 @@ from __future__ import annotations -from typing import Optional +from typing import Optional, TYPE_CHECKING from attrs import define, field from griptape.artifacts import InfoArtifact, ListArtifact, ErrorArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.loaders import SqlLoader from schema import Schema +if TYPE_CHECKING: + from griptape.loaders import SqlLoader + @define class SqlClient(BaseTool): diff --git a/griptape/tools/structure_run_client/tool.py b/griptape/tools/structure_run_client/tool.py index f48e84a1d..fe6d33f85 100644 --- a/griptape/tools/structure_run_client/tool.py +++ b/griptape/tools/structure_run_client/tool.py @@ -4,9 +4,12 @@ from schema import Literal, Schema from griptape.artifacts import BaseArtifact, TextArtifact -from griptape.drivers import BaseStructureRunDriver from griptape.tools.base_tool import BaseTool from griptape.utils.decorators import activity +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.drivers import BaseStructureRunDriver @define diff --git a/griptape/tools/text_to_speech_client/tool.py b/griptape/tools/text_to_speech_client/tool.py index 9f8c36a81..675320d83 100644 --- a/griptape/tools/text_to_speech_client/tool.py +++ b/griptape/tools/text_to_speech_client/tool.py @@ -1,16 +1,18 @@ from __future__ import annotations -from typing import Any +from typing import Any, TYPE_CHECKING from attrs import define, field from schema import Schema, Literal -from griptape.artifacts import ErrorArtifact, AudioArtifact -from griptape.engines import TextToSpeechEngine from griptape.tools import BaseTool from griptape.utils.decorators import activity from griptape.mixins import BlobArtifactFileOutputMixin +if TYPE_CHECKING: + from griptape.engines import TextToSpeechEngine + from griptape.artifacts import ErrorArtifact, AudioArtifact + @define class TextToSpeechClient(BlobArtifactFileOutputMixin, BaseTool): diff --git a/griptape/tools/variation_image_generation_client/tool.py b/griptape/tools/variation_image_generation_client/tool.py index 4d0d0537e..40afab05a 100644 --- a/griptape/tools/variation_image_generation_client/tool.py +++ b/griptape/tools/variation_image_generation_client/tool.py @@ -1,18 +1,20 @@ from __future__ import annotations -from typing import Any, cast +from typing import Any, cast, TYPE_CHECKING from attrs import define, field from schema import Schema, Literal from griptape.artifacts import ErrorArtifact, ImageArtifact -from griptape.engines import VariationImageGenerationEngine from griptape.loaders import ImageLoader from griptape.tools import BaseTool from griptape.utils.decorators import activity from griptape.mixins import BlobArtifactFileOutputMixin from griptape.utils.load_artifact_from_memory import load_artifact_from_memory +if TYPE_CHECKING: + from griptape.engines import VariationImageGenerationEngine + @define class VariationImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index 8d4e73022..a1d7463a7 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -1,13 +1,15 @@ from __future__ import annotations -from typing import Callable, Any +from typing import Callable, Any, TYPE_CHECKING from attrs import define, field, Factory from schema import Schema, Literal from griptape.artifacts import ErrorArtifact, BaseArtifact from griptape.artifacts import ListArtifact -from griptape.drivers import BaseVectorStoreDriver from griptape.tools import BaseTool from griptape.utils.decorators import activity +if TYPE_CHECKING: + from griptape.drivers import BaseVectorStoreDriver + @define(kw_only=True) class VectorStoreClient(BaseTool): diff --git a/griptape/tools/web_search/tool.py b/griptape/tools/web_search/tool.py index e5dc9add7..17c62dcc4 100644 --- a/griptape/tools/web_search/tool.py +++ b/griptape/tools/web_search/tool.py @@ -4,7 +4,10 @@ from schema import Schema, Literal from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.drivers import BaseWebSearchDriver +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.drivers import BaseWebSearchDriver @define diff --git a/griptape/utils/stream.py b/griptape/utils/stream.py index 8cb2c3a7c..18df1ba56 100644 --- a/griptape/utils/stream.py +++ b/griptape/utils/stream.py @@ -1,17 +1,17 @@ from __future__ import annotations from typing import TYPE_CHECKING -from collections.abc import Iterator from threading import Thread from queue import Queue from griptape.artifacts.text_artifact import TextArtifact from griptape.events.completion_chunk_event import CompletionChunkEvent from griptape.events.event_listener import EventListener -from griptape.events.base_event import BaseEvent from griptape.events.finish_structure_run_event import FinishStructureRunEvent from griptape.events.finish_prompt_event import FinishPromptEvent from attrs import field, define, Factory if TYPE_CHECKING: + from collections.abc import Iterator + from griptape.events.base_event import BaseEvent from griptape.structures import Structure diff --git a/pyproject.toml b/pyproject.toml index c315e9ffa..e2c4fdfd4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -209,6 +209,7 @@ select = [ "SIM", # flake8-simplify "TID251", # banned-api "T201", # print + "TCH" ] ignore = [ "UP007", # non-pep604-annotation From 7ed02ccb04c58868d984b949b037f68c0853f9b9 Mon Sep 17 00:00:00 2001 From: Vasily Vasinov Date: Thu, 11 Jul 2024 09:54:49 -0600 Subject: [PATCH 54/87] Fix RagClient docs (#961) --- .../official-tools/rag-client.md | 55 ++++++++++++++----- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/docs/griptape-tools/official-tools/rag-client.md b/docs/griptape-tools/official-tools/rag-client.md index 6c8f9f17d..b11287b3e 100644 --- a/docs/griptape-tools/official-tools/rag-client.md +++ b/docs/griptape-tools/official-tools/rag-client.md @@ -3,29 +3,28 @@ The [RagClient](../../reference/griptape/tools/rag_client/tool.md) enables LLMs Here is an example of how it can be used with a local vector store driver: ```python -from griptape.structures import Agent -from griptape.tasks import RagTask -from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.artifacts import TextArtifact +from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.engines.rag import RagEngine from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage +from griptape.structures import Agent +from griptape.tools import RagClient + -# Initialize Embedding Driver and Vector Store Driver vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) artifact = TextArtifact( "Griptape builds AI-powered applications that connect securely to your enterprise data and APIs." "Griptape Agents provide incredible power and flexibility when working with large language models." ) + vector_store_driver.upsert_text_artifact(artifact=artifact, namespace="griptape") -# Instantiate the agent and add RagTask with the RagEngine -agent = Agent() -agent.add_task( - RagTask( - "Respond to the following query: {{ args[0] }}", - rag_engine=RagEngine( +rag_client = RagClient( + description="Contains information about Griptape", + off_prompt=False, + rag_engine=RagEngine( retrieval_stage=RetrievalRagStage( retrieval_modules=[ VectorStoreRetrievalRagModule( @@ -42,10 +41,38 @@ agent.add_task( prompt_driver=OpenAiChatPromptDriver(model="gpt-4o") ) ) - ), - ) + ) +) + +agent = Agent( + tools=[rag_client] ) -# Run the agent with a query string -agent.run("Give me information about Griptape") +agent.run("what is Griptape?") + +``` ``` +[07/11/24 08:47:04] INFO ToolkitTask 4a5308b86cac447783e6abe1be0646cd + Input: what is Griptape? +[07/11/24 08:47:06] INFO Subtask e034a5d82658411694e9e19e51fa6699 + Thought: I need to search for information about + Griptape using the RagClient. I will perform a + search query to gather relevant details. + + Actions: + [{"name":"RagClient","path":"search","input":{"valu + es":{"query":"What is + Griptape?"}},"tag":"search_griptape"}] +[07/11/24 08:47:08] INFO Subtask e034a5d82658411694e9e19e51fa6699 + Response: Griptape builds AI-powered applications + that connect securely to your enterprise data and + APIs. Griptape Agents provide incredible power and + flexibility when working with large language + models. +[07/11/24 08:47:09] INFO ToolkitTask 4a5308b86cac447783e6abe1be0646cd + Output: Griptape builds AI-powered applications + that connect securely to your enterprise data and + APIs. Griptape Agents provide incredible power and + flexibility when working with large language + models. +``` \ No newline at end of file From 160a4ef741aa5b6640e07ffe13009a75e74c2384 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 11 Jul 2024 10:22:01 -0700 Subject: [PATCH 55/87] Enable ruff pydocstyle rules (#959) --- griptape/artifacts/boolean_artifact.py | 4 +--- griptape/artifacts/media_artifact.py | 3 +-- .../amazon_bedrock_cohere_embedding_driver.py | 3 ++- .../amazon_bedrock_titan_embedding_driver.py | 3 ++- .../azure_openai_embedding_driver.py | 3 ++- .../embedding/base_embedding_driver.py | 3 ++- .../embedding/cohere_embedding_driver.py | 3 ++- .../embedding/google_embedding_driver.py | 3 ++- .../huggingface_hub_embedding_driver.py | 3 ++- .../embedding/ollama_embedding_driver.py | 3 ++- .../embedding/openai_embedding_driver.py | 3 ++- .../embedding/voyageai_embedding_driver.py | 3 ++- .../amazon_s3_file_manager_driver.py | 3 +-- .../file_manager/base_file_manager_driver.py | 3 +-- .../file_manager/local_file_manager_driver.py | 3 +-- .../anthropic_image_query_driver.py | 3 ++- .../drivers/prompt/anthropic_prompt_driver.py | 3 ++- .../prompt/azure_openai_chat_prompt_driver.py | 3 ++- griptape/drivers/prompt/base_prompt_driver.py | 1 + .../drivers/prompt/cohere_prompt_driver.py | 3 ++- .../drivers/prompt/google_prompt_driver.py | 3 ++- .../prompt/huggingface_hub_prompt_driver.py | 4 ++-- .../huggingface_pipeline_prompt_driver.py | 4 ++-- .../drivers/prompt/ollama_prompt_driver.py | 3 ++- .../prompt/openai_chat_prompt_driver.py | 3 ++- .../amazon_opensearch_vector_store_driver.py | 1 - .../vector/marqo_vector_store_driver.py | 19 ++++++++---------- .../vector/opensearch_vector_store_driver.py | 2 -- .../vector/pgvector_vector_store_driver.py | 11 ++-------- .../vector/qdrant_vector_store_driver.py | 20 +++++++------------ griptape/engines/rag/rag_context.py | 3 +-- griptape/loaders/email_loader.py | 2 +- griptape/mixins/serializable_mixin.py | 1 + griptape/schemas/polymorphic_schema.py | 10 +++------- griptape/structures/workflow.py | 1 - griptape/tasks/actions_subtask.py | 2 ++ griptape/tasks/image_query_task.py | 6 ++++-- .../tasks/inpainting_image_generation_task.py | 6 ++++-- .../outpainting_image_generation_task.py | 6 ++++-- .../tasks/prompt_image_generation_task.py | 6 ++++-- .../tasks/variation_image_generation_task.py | 6 ++++-- griptape/tokenizers/openai_tokenizer.py | 7 ++++--- griptape/tools/base_griptape_cloud_client.py | 3 ++- griptape/tools/email_client/tool.py | 2 +- griptape/tools/file_manager/tool.py | 3 +-- .../tool.py | 3 ++- griptape/tools/rag_client/tool.py | 3 ++- griptape/tools/rest_api_client/tool.py | 3 ++- griptape/tools/structure_run_client/tool.py | 3 ++- griptape/tools/vector_store_client/tool.py | 3 ++- griptape/utils/dict_utils.py | 4 +++- griptape/utils/file_utils.py | 1 - griptape/utils/import_utils.py | 3 ++- griptape/utils/structure_visualizer.py | 7 ++++--- pyproject.toml | 13 +++++++++++- 55 files changed, 128 insertions(+), 108 deletions(-) diff --git a/griptape/artifacts/boolean_artifact.py b/griptape/artifacts/boolean_artifact.py index e7e440f45..0c5ae6f35 100644 --- a/griptape/artifacts/boolean_artifact.py +++ b/griptape/artifacts/boolean_artifact.py @@ -10,9 +10,7 @@ class BooleanArtifact(BaseArtifact): @classmethod def parse_bool(cls, value: Union[str, bool]) -> BooleanArtifact: - """ - Convert a string literal or bool to a BooleanArtifact. The string must be either "true" or "false" with any casing. - """ + """Convert a string literal or bool to a BooleanArtifact. The string must be either "true" or "false" with any casing.""" if value is not None: if isinstance(value, str): if value.lower() == "true": diff --git a/griptape/artifacts/media_artifact.py b/griptape/artifacts/media_artifact.py index 2848ec1bb..751f2bf62 100644 --- a/griptape/artifacts/media_artifact.py +++ b/griptape/artifacts/media_artifact.py @@ -12,8 +12,7 @@ @define class MediaArtifact(BlobArtifact): - """MediaArtifact is a type of BlobArtifact that represents media (image, audio, video, etc.) - and can be extended to support a specific media type. + """MediaArtifact is a type of BlobArtifact that represents media (image, audio, video, etc.) and can be extended to support a specific media type. Attributes: value: Raw bytes representing media data. diff --git a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py index 8a70c98e2..fe113c300 100644 --- a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py @@ -13,7 +13,8 @@ @define class AmazonBedrockCohereEmbeddingDriver(BaseEmbeddingDriver): - """ + """Amazon Bedrock Cohere Embedding Driver. + Attributes: model: Embedding model name. Defaults to DEFAULT_MODEL. input_type: Defaults to `search_query`. Prepends special tokens to differentiate each type from one another: diff --git a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py index d90eefba7..1de4d6cfe 100644 --- a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py @@ -13,7 +13,8 @@ @define class AmazonBedrockTitanEmbeddingDriver(BaseEmbeddingDriver): - """ + """Amazon Bedrock Titan Embedding Driver. + Attributes: model: Embedding model name. Defaults to DEFAULT_MODEL. tokenizer: Optionally provide custom `BedrockTitanTokenizer`. diff --git a/griptape/drivers/embedding/azure_openai_embedding_driver.py b/griptape/drivers/embedding/azure_openai_embedding_driver.py index c92197e9b..bf78ef1ae 100644 --- a/griptape/drivers/embedding/azure_openai_embedding_driver.py +++ b/griptape/drivers/embedding/azure_openai_embedding_driver.py @@ -9,7 +9,8 @@ @define class AzureOpenAiEmbeddingDriver(OpenAiEmbeddingDriver): - """ + """Azure OpenAi Embedding Driver. + Attributes: azure_deployment: An optional Azure OpenAi deployment id. Defaults to the model name. azure_endpoint: An Azure OpenAi endpoint. diff --git a/griptape/drivers/embedding/base_embedding_driver.py b/griptape/drivers/embedding/base_embedding_driver.py index a92fa325a..dc9e2c9ae 100644 --- a/griptape/drivers/embedding/base_embedding_driver.py +++ b/griptape/drivers/embedding/base_embedding_driver.py @@ -14,7 +14,8 @@ @define class BaseEmbeddingDriver(SerializableMixin, ExponentialBackoffMixin, ABC): - """ + """Base Embedding Driver. + Attributes: model: The name of the model to use. tokenizer: An instance of `BaseTokenizer` to use when calculating tokens. diff --git a/griptape/drivers/embedding/cohere_embedding_driver.py b/griptape/drivers/embedding/cohere_embedding_driver.py index 5e8bdf4dd..13f72aa16 100644 --- a/griptape/drivers/embedding/cohere_embedding_driver.py +++ b/griptape/drivers/embedding/cohere_embedding_driver.py @@ -11,7 +11,8 @@ @define class CohereEmbeddingDriver(BaseEmbeddingDriver): - """ + """Cohere Embedding Driver. + Attributes: api_key: Cohere API key. model: Cohere model name. diff --git a/griptape/drivers/embedding/google_embedding_driver.py b/griptape/drivers/embedding/google_embedding_driver.py index 884a40c3c..b8745345c 100644 --- a/griptape/drivers/embedding/google_embedding_driver.py +++ b/griptape/drivers/embedding/google_embedding_driver.py @@ -7,7 +7,8 @@ @define class GoogleEmbeddingDriver(BaseEmbeddingDriver): - """ + """Google Embedding Driver. + Attributes: api_key: Google API key. model: Google model name. diff --git a/griptape/drivers/embedding/huggingface_hub_embedding_driver.py b/griptape/drivers/embedding/huggingface_hub_embedding_driver.py index 71abef81f..8b47e56e9 100644 --- a/griptape/drivers/embedding/huggingface_hub_embedding_driver.py +++ b/griptape/drivers/embedding/huggingface_hub_embedding_driver.py @@ -10,7 +10,8 @@ @define class HuggingFaceHubEmbeddingDriver(BaseEmbeddingDriver): - """ + """Hugging Face Hub Embedding Driver. + Attributes: api_token: Hugging Face Hub API token. model: Hugging Face Hub model name. diff --git a/griptape/drivers/embedding/ollama_embedding_driver.py b/griptape/drivers/embedding/ollama_embedding_driver.py index d081321c1..f3f68a049 100644 --- a/griptape/drivers/embedding/ollama_embedding_driver.py +++ b/griptape/drivers/embedding/ollama_embedding_driver.py @@ -10,7 +10,8 @@ @define class OllamaEmbeddingDriver(BaseEmbeddingDriver): - """ + """Ollama Embedding Driver. + Attributes: model: Ollama embedding model name. host: Optional Ollama host. diff --git a/griptape/drivers/embedding/openai_embedding_driver.py b/griptape/drivers/embedding/openai_embedding_driver.py index 089875c1a..46b9e77b5 100644 --- a/griptape/drivers/embedding/openai_embedding_driver.py +++ b/griptape/drivers/embedding/openai_embedding_driver.py @@ -8,7 +8,8 @@ @define class OpenAiEmbeddingDriver(BaseEmbeddingDriver): - """ + """OpenAI Embedding Driver. + Attributes: model: OpenAI embedding model name. Defaults to `text-embedding-3-small`. base_url: API URL. Defaults to OpenAI's v1 API URL. diff --git a/griptape/drivers/embedding/voyageai_embedding_driver.py b/griptape/drivers/embedding/voyageai_embedding_driver.py index 0cfac6fda..76bcf71b8 100644 --- a/griptape/drivers/embedding/voyageai_embedding_driver.py +++ b/griptape/drivers/embedding/voyageai_embedding_driver.py @@ -8,7 +8,8 @@ @define class VoyageAiEmbeddingDriver(BaseEmbeddingDriver): - """ + """VoyageAI Embedding Driver. + Attributes: model: VoyageAI embedding model name. Defaults to `voyage-large-2`. api_key: API key to pass directly. Defaults to `VOYAGE_API_KEY` environment variable. diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index e2d794f31..840ae60d7 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -12,8 +12,7 @@ @define class AmazonS3FileManagerDriver(BaseFileManagerDriver): - """ - AmazonS3FileManagerDriver can be used to list, load, and save files in an Amazon S3 bucket. + """AmazonS3FileManagerDriver can be used to list, load, and save files in an Amazon S3 bucket. Attributes: session: The boto3 session to use for S3 operations. diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index 9b8fe8325..546642554 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -7,8 +7,7 @@ @define class BaseFileManagerDriver(ABC): - """ - BaseFileManagerDriver can be used to list, load, and save files. + """BaseFileManagerDriver can be used to list, load, and save files. Attributes: default_loader: The default loader to use for loading file contents into artifacts. diff --git a/griptape/drivers/file_manager/local_file_manager_driver.py b/griptape/drivers/file_manager/local_file_manager_driver.py index 186296aa3..befe2fdd2 100644 --- a/griptape/drivers/file_manager/local_file_manager_driver.py +++ b/griptape/drivers/file_manager/local_file_manager_driver.py @@ -7,8 +7,7 @@ @define class LocalFileManagerDriver(BaseFileManagerDriver): - """ - LocalFileManagerDriver can be used to list, load, and save files on the local file system. + """LocalFileManagerDriver can be used to list, load, and save files on the local file system. Attributes: workdir: The absolute working directory. List, load, and save operations will be performed relative to this directory. diff --git a/griptape/drivers/image_query/anthropic_image_query_driver.py b/griptape/drivers/image_query/anthropic_image_query_driver.py index aca06ac2f..9bc9ec4ae 100644 --- a/griptape/drivers/image_query/anthropic_image_query_driver.py +++ b/griptape/drivers/image_query/anthropic_image_query_driver.py @@ -8,7 +8,8 @@ @define class AnthropicImageQueryDriver(BaseImageQueryDriver): - """ + """Anthropic Image Query Driver. + Attributes: api_key: Anthropic API key. model: Anthropic model name. diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 5ef28e143..877e41621 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -42,7 +42,8 @@ @define class AnthropicPromptDriver(BasePromptDriver): - """ + """Anthropic Prompt Driver. + Attributes: api_key: Anthropic API key. model: Anthropic model name. diff --git a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py index 64145b1a9..0b33aa103 100644 --- a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py @@ -7,7 +7,8 @@ @define class AzureOpenAiChatPromptDriver(OpenAiChatPromptDriver): - """ + """Azure OpenAi Chat Prompt Driver. + Attributes: azure_deployment: An optional Azure OpenAi deployment id. Defaults to the model name. azure_endpoint: An Azure OpenAi endpoint. diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index e36654b23..f012e7339 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -79,6 +79,7 @@ def run(self, prompt_stack: PromptStack) -> Message: def prompt_stack_to_string(self, prompt_stack: PromptStack) -> str: """Converts a Prompt Stack to a string for token counting or model input. + This base implementation is only a rough approximation, and should be overridden by subclasses with model-specific tokens. Args: diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index b2cc6ea83..a5dccb2a5 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -31,7 +31,8 @@ @define(kw_only=True) class CoherePromptDriver(BasePromptDriver): - """ + """Cohere Prompt Driver. + Attributes: api_key: Cohere API key. model: Cohere model name. diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index c1ef91ec8..48bb29f59 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -37,7 +37,8 @@ @define class GooglePromptDriver(BasePromptDriver): - """ + """Google Prompt Driver. + Attributes: api_key: Google API key. model: Google model name. diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index ae080e34b..1c5647856 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -16,7 +16,8 @@ @define class HuggingFaceHubPromptDriver(BasePromptDriver): - """ + """Hugging Face Hub Prompt Driver. + Attributes: api_token: Hugging Face Hub API token. use_gpu: Use GPU during model run. @@ -24,7 +25,6 @@ class HuggingFaceHubPromptDriver(BasePromptDriver): model: Hugging Face Hub model name. client: Custom `InferenceApi`. tokenizer: Custom `HuggingFaceTokenizer`. - """ api_token: str = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index cd77deefe..9273deb0c 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -17,11 +17,11 @@ @define class HuggingFacePipelinePromptDriver(BasePromptDriver): - """ + """Hugging Face Pipeline Prompt Driver. + Attributes: params: Custom model run parameters. model: Hugging Face Hub model name. - """ max_tokens: int = field(default=250, kw_only=True, metadata={"serializable": True}) diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py index d554b7c96..0818bd5e8 100644 --- a/griptape/drivers/prompt/ollama_prompt_driver.py +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -17,7 +17,8 @@ @define class OllamaPromptDriver(BasePromptDriver): - """ + """Ollama Prompt Driver. + Attributes: model: Model name. """ diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index 755e05f56..c6bd02489 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -35,7 +35,8 @@ @define class OpenAiChatPromptDriver(BasePromptDriver): - """ + """OpenAI Chat Prompt Driver. + Attributes: base_url: An optional OpenAi API URL. api_key: An optional OpenAi API key. If not provided, the `OPENAI_API_KEY` environment variable will be used. diff --git a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py index 668f89b7e..d53ac2c64 100644 --- a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py @@ -57,7 +57,6 @@ def upsert_vector( If a vector with the given vector ID already exists, it is updated; otherwise, a new vector is inserted. Metadata associated with the vector can also be provided. """ - vector_id = vector_id if vector_id else str_to_hash(str(vector)) doc = {"vector": vector, "namespace": namespace, "metadata": meta} doc.update(kwargs) diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index a46f4b02f..2e4d0acf0 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -37,7 +37,7 @@ def upsert_text( vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, - **kwargs, + **kwargs: Any, ) -> str: """Upsert a text document into the Marqo index. @@ -46,11 +46,11 @@ def upsert_text( vector_id: The ID for the vector. If None, Marqo will generate an ID. namespace: An optional namespace for the document. meta: An optional dictionary of metadata for the document. + kwargs: Additional keyword arguments to pass to the Marqo client. Returns: str: The ID of the document that was added. """ - doc = {"_id": vector_id, "Description": string} # Description will be treated as tensor field # Non-tensor fields @@ -71,7 +71,7 @@ def upsert_text_artifact( namespace: Optional[str] = None, meta: Optional[dict] = None, vector_id: Optional[str] = None, - **kwargs, + **kwargs: Any, ) -> str: """Upsert a text artifact into the Marqo index. @@ -80,11 +80,11 @@ def upsert_text_artifact( namespace: An optional namespace for the artifact. meta: An optional dictionary of metadata for the artifact. vector_id: An optional explicit vector_id. + kwargs: Additional keyword arguments to pass to the Marqo client. Returns: str: The ID of the artifact that was added. """ - artifact_json = artifact.to_json() vector_id = utils.str_to_hash(artifact.value) if vector_id is None else vector_id @@ -131,7 +131,6 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD Returns: The list of loaded Entries. """ - filter_string = f"namespace:{namespace}" if namespace else None if filter_string is not None: @@ -167,7 +166,7 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, include_metadata: bool = True, - **kwargs, + **kwargs: Any, ) -> list[BaseVectorStoreDriver.Entry]: """Query the Marqo index for documents. @@ -177,11 +176,11 @@ def query( namespace: The namespace to filter results by. include_vectors: Whether to include vector data in the results. include_metadata: Whether to include metadata in the results. + kwargs: Additional keyword arguments to pass to the Marqo client. Returns: The list of query results. """ - params = { "limit": count if count else BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, "attributes_to_retrieve": ["*"] if include_metadata else ["_id"], @@ -211,7 +210,6 @@ def delete_index(self, name: str) -> dict[str, Any]: Args: name: The name of the index to delete. """ - return self.mq.delete_index(name) def get_indexes(self) -> list[str]: @@ -220,7 +218,6 @@ def get_indexes(self) -> list[str]: Returns: The list of all indexes. """ - return [index["index"] for index in self.mq.get_indexes()["results"]] def upsert_vector( @@ -229,7 +226,7 @@ def upsert_vector( vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, - **kwargs, + **kwargs: Any, ) -> str: """Upsert a vector into the Marqo index. @@ -238,6 +235,7 @@ def upsert_vector( vector_id: The ID for the vector. If None, Marqo will generate an ID. namespace: An optional namespace for the vector. meta: An optional dictionary of metadata for the vector. + kwargs: Additional keyword arguments to pass to the Marqo client. Raises: Exception: This function is not yet implemented. @@ -245,7 +243,6 @@ def upsert_vector( Returns: The ID of the vector that was added. """ - raise NotImplementedError(f"{self.__class__.__name__} does not support upserting a vector.") def delete_vector(self, vector_id: str): diff --git a/griptape/drivers/vector/opensearch_vector_store_driver.py b/griptape/drivers/vector/opensearch_vector_store_driver.py index 81add74aa..49e73af96 100644 --- a/griptape/drivers/vector/opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/opensearch_vector_store_driver.py @@ -56,7 +56,6 @@ def upsert_vector( If a vector with the given vector ID already exists, it is updated; otherwise, a new vector is inserted. Metadata associated with the vector can also be provided. """ - vector_id = vector_id if vector_id else utils.str_to_hash(str(vector)) doc = {"vector": vector, "namespace": namespace, "metadata": meta} doc.update(kwargs) @@ -99,7 +98,6 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD Returns: A list of BaseVectorStoreDriver.Entry objects. """ - query_body = {"size": 10000, "query": {"match_all": {}}} if namespace: diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index 29c657589..abe01098a 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -53,9 +53,6 @@ def validate_engine(self, _, engine: Optional[Engine]) -> None: raise ValueError("An engine or connection string is required") def __attrs_post_init__(self) -> None: - """If an engine is provided, it will be used to connect to the database. - If not, a connection string is used to create a new database connection here. - """ if self.engine is None: self.engine = cast(Engine, create_engine(self.connection_string, **self.create_engine_params)) @@ -102,9 +99,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> BaseVec ) def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: - """Retrieves all vector entries from the collection, optionally filtering to only - those that match the provided namespace. - """ + """Retrieves all vector entries from the collection, optionally filtering to only those that match the provided namespace.""" with Session(self.engine) as session: query = session.query(self._model) if namespace: @@ -128,9 +123,7 @@ def query( distance_metric: str = "cosine_distance", **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: - """Performs a search on the collection to find vectors similar to the provided input vector, - optionally filtering to only those that match the provided namespace. - """ + """Performs a search on the collection to find vectors similar to the provided input vector, optionally filtering to only those that match the provided namespace.""" distance_metrics = { "cosine_distance": self._model.vector.cosine_distance, "l2_distance": self._model.vector.l2_distance, diff --git a/griptape/drivers/vector/qdrant_vector_store_driver.py b/griptape/drivers/vector/qdrant_vector_store_driver.py index 5159bdb0a..0b96f03b9 100644 --- a/griptape/drivers/vector/qdrant_vector_store_driver.py +++ b/griptape/drivers/vector/qdrant_vector_store_driver.py @@ -12,7 +12,8 @@ @define class QdrantVectorStoreDriver(BaseVectorStoreDriver): - """ + """Vector Store Driver for Qdrant. + Attributes: location: An optional location for the Qdrant client. If set to ':memory:', an in-memory client is used. url: An optional Qdrant API URL. @@ -68,8 +69,7 @@ def __attrs_post_init__(self) -> None: ) def delete_vector(self, vector_id: str) -> None: - """ - Delete a vector from the Qdrant collection based on its ID. + """Delete a vector from the Qdrant collection based on its ID. Parameters: vector_id (str | id): ID of the vector to delete. @@ -89,8 +89,7 @@ def query( include_vectors: bool = False, **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: - """ - Query the Qdrant collection based on a query vector. + """Query the Qdrant collection based on a query vector. Parameters: query (str): Query string. @@ -127,8 +126,7 @@ def upsert_vector( content: Optional[str] = None, **kwargs, ) -> str: - """ - Upsert vectors into the Qdrant collection. + """Upsert vectors into the Qdrant collection. Parameters: vector (list[float]): The vector to be upserted. @@ -140,7 +138,6 @@ def upsert_vector( Returns: str: The ID of the upserted vector. """ - if vector_id is None: vector_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, str(vector))) @@ -158,8 +155,7 @@ def upsert_vector( return vector_id def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: - """ - Load a vector entry from the Qdrant collection based on its ID. + """Load a vector entry from the Qdrant collection based on its ID. Parameters: vector_id (str): ID of the vector to load. @@ -180,8 +176,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona return None def load_entries(self, namespace: Optional[str] = None, **kwargs) -> list[BaseVectorStoreDriver.Entry]: - """ - Load vector entries from the Qdrant collection. + """Load vector entries from the Qdrant collection. Parameters: namespace: Optional namespace of the vectors. @@ -189,7 +184,6 @@ def load_entries(self, namespace: Optional[str] = None, **kwargs) -> list[BaseVe Returns: List of points. """ - results = self.client.retrieve( collection_name=self.collection_name, ids=kwargs.get("ids", []), diff --git a/griptape/engines/rag/rag_context.py b/griptape/engines/rag/rag_context.py index e6f111279..be4807599 100644 --- a/griptape/engines/rag/rag_context.py +++ b/griptape/engines/rag/rag_context.py @@ -12,8 +12,7 @@ @define(kw_only=True) class RagContext(SerializableMixin): - """Used by RagEngine stages and module to pass context that individual modules are expected to update in the `run` - method. + """Used by RagEngine stages and module to pass context that individual modules are expected to update in the `run` method. Attributes: query: Query provided by the user. diff --git a/griptape/loaders/email_loader.py b/griptape/loaders/email_loader.py index a7598e2a6..3d0ad1358 100644 --- a/griptape/loaders/email_loader.py +++ b/griptape/loaders/email_loader.py @@ -15,7 +15,7 @@ class EmailLoader(BaseLoader): @define(frozen=True) class EmailQuery: - """An email retrieval query + """An email retrieval query. Attributes: label: Label to retrieve emails from such as 'INBOX' or 'SENT'. diff --git a/griptape/mixins/serializable_mixin.py b/griptape/mixins/serializable_mixin.py index 5535c69c6..2364e8bc4 100644 --- a/griptape/mixins/serializable_mixin.py +++ b/griptape/mixins/serializable_mixin.py @@ -64,6 +64,7 @@ def to_dict(self) -> dict: @classmethod def _import_cls_rec(cls, module_name: str, class_name: str) -> type: """Imports a class given a module name and class name. + Will recursively traverse up the module's path until it finds a package that it can import `class_name` from. diff --git a/griptape/schemas/polymorphic_schema.py b/griptape/schemas/polymorphic_schema.py index 452e3001f..60001de18 100644 --- a/griptape/schemas/polymorphic_schema.py +++ b/griptape/schemas/polymorphic_schema.py @@ -4,9 +4,7 @@ class PolymorphicSchema(BaseSchema): - """ - PolymorphicSchema is based on https://github.com/marshmallow-code/marshmallow-oneofschema - """ + """PolymorphicSchema is based on https://github.com/marshmallow-code/marshmallow-oneofschema.""" def __init__(self, inner_class: Any, **kwargs): super().__init__(**kwargs) @@ -17,13 +15,11 @@ def __init__(self, inner_class: Any, **kwargs): type_field_remove = True def get_obj_type(self, obj): - """Returns name of the schema during dump() calls, given the object - being dumped.""" + """Returns name of the schema during dump() calls, given the object being dumped.""" return obj.__class__.__name__ def get_data_type(self, data): - """Returns name of the schema during load() calls, given the data being - loaded. Defaults to looking up `type_field` in the data.""" + """Returns name of the schema during load() calls, given the data being loaded. Defaults to looking up `type_field` in the data.""" data_type = data.get(self.type_field) if self.type_field in data and self.type_field_remove: data.pop(self.type_field) diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index ffb3bf721..3c0ee6586 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -43,7 +43,6 @@ def insert_tasks( child_tasks: The tasks that will be the children of the new tasks. preserve_relationship: Whether to preserve the parent/child relationship when inserting between parent and child tasks. """ - if not isinstance(parent_tasks, list): parent_tasks = [parent_tasks] if not isinstance(tasks, list): diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index da378f881..ac0503e8f 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -208,10 +208,12 @@ def __init_from_prompt(self, value: str) -> None: def __init_from_artifacts(self, artifacts: ListArtifact) -> None: """Parses the input Artifacts to extract the thought and actions. + Text Artifacts are used to extract the thought, and ToolAction Artifacts are used to extract the actions. Args: artifacts: The input Artifacts. + Returns: None """ diff --git a/griptape/tasks/image_query_task.py b/griptape/tasks/image_query_task.py index 85b25715a..aac3c655b 100644 --- a/griptape/tasks/image_query_task.py +++ b/griptape/tasks/image_query_task.py @@ -12,11 +12,13 @@ @define class ImageQueryTask(BaseTask): - """A task that executes a natural language query on one or more input images. Accepts a text prompt and a list of + """A task that executes a natural language query on one or more input images. + + Accepts a text prompt and a list of images as input in one of the following formats: - tuple of (template string, list[ImageArtifact]) - tuple of (TextArtifact, list[ImageArtifact]) - - Callable that returns a tuple of (TextArtifact, list[ImageArtifact]) + - Callable that returns a tuple of (TextArtifact, list[ImageArtifact]). Attributes: image_query_engine: The engine used to execute the query. diff --git a/griptape/tasks/inpainting_image_generation_task.py b/griptape/tasks/inpainting_image_generation_task.py index b0fae9118..838ab4489 100644 --- a/griptape/tasks/inpainting_image_generation_task.py +++ b/griptape/tasks/inpainting_image_generation_task.py @@ -12,11 +12,13 @@ @define class InpaintingImageGenerationTask(BaseImageGenerationTask): - """A task that modifies a select region within an image using a mask. Accepts a text prompt, image, and mask as + """A task that modifies a select region within an image using a mask. + + Accepts a text prompt, image, and mask as input in one of the following formats: - tuple of (template string, ImageArtifact, ImageArtifact) - tuple of (TextArtifact, ImageArtifact, ImageArtifact) - - Callable that returns a tuple of (TextArtifact, ImageArtifact, ImageArtifact) + - Callable that returns a tuple of (TextArtifact, ImageArtifact, ImageArtifact). Attributes: image_generation_engine: The engine used to generate the image. diff --git a/griptape/tasks/outpainting_image_generation_task.py b/griptape/tasks/outpainting_image_generation_task.py index 61a7c1b8a..135304ad3 100644 --- a/griptape/tasks/outpainting_image_generation_task.py +++ b/griptape/tasks/outpainting_image_generation_task.py @@ -12,11 +12,13 @@ @define class OutpaintingImageGenerationTask(BaseImageGenerationTask): - """A task that modifies an image outside the bounds of a mask. Accepts a text prompt, image, and mask as + """A task that modifies an image outside the bounds of a mask. + + Accepts a text prompt, image, and mask as input in one of the following formats: - tuple of (template string, ImageArtifact, ImageArtifact) - tuple of (TextArtifact, ImageArtifact, ImageArtifact) - - Callable that returns a tuple of (TextArtifact, ImageArtifact, ImageArtifact) + - Callable that returns a tuple of (TextArtifact, ImageArtifact, ImageArtifact). Attributes: image_generation_engine: The engine used to generate the image. diff --git a/griptape/tasks/prompt_image_generation_task.py b/griptape/tasks/prompt_image_generation_task.py index 577abacbb..8c487d1ed 100644 --- a/griptape/tasks/prompt_image_generation_task.py +++ b/griptape/tasks/prompt_image_generation_task.py @@ -12,10 +12,12 @@ @define class PromptImageGenerationTask(BaseImageGenerationTask): - """Used to generate an image from a text prompt. Accepts prompt as input in one of the following formats: + """Used to generate an image from a text prompt. + + Accepts prompt as input in one of the following formats: - template string - TextArtifact - - Callable that returns a TextArtifact + - Callable that returns a TextArtifact. Attributes: image_generation_engine: The engine used to generate the image. diff --git a/griptape/tasks/variation_image_generation_task.py b/griptape/tasks/variation_image_generation_task.py index 6efba1e65..1f2cebbfc 100644 --- a/griptape/tasks/variation_image_generation_task.py +++ b/griptape/tasks/variation_image_generation_task.py @@ -12,11 +12,13 @@ @define class VariationImageGenerationTask(BaseImageGenerationTask): - """A task that generates a variation of an image using a prompt. Accepts a text prompt and image as + """A task that generates a variation of an image using a prompt. + + Accepts a text prompt and image as input in one of the following formats: - tuple of (template string, ImageArtifact) - tuple of (TextArtifact, ImageArtifact) - - Callable that returns a tuple of (TextArtifact, ImageArtifact) + - Callable that returns a tuple of (TextArtifact, ImageArtifact). Attributes: image_generation_engine: The engine used to generate the image. diff --git a/griptape/tokenizers/openai_tokenizer.py b/griptape/tokenizers/openai_tokenizer.py index a58ec5ce5..3cb2674cf 100644 --- a/griptape/tokenizers/openai_tokenizer.py +++ b/griptape/tokenizers/openai_tokenizer.py @@ -75,9 +75,10 @@ def _default_max_output_tokens(self) -> int: return tokens def count_tokens(self, text: str | list[dict], model: Optional[str] = None) -> int: - """ - Handles the special case of ChatML. Implementation adopted from the official OpenAI notebook: - https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb + """Handles the special case of ChatML. + + Implementation adopted from the official OpenAI notebook: + https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb. """ if isinstance(text, list): model = model if model else self.model diff --git a/griptape/tools/base_griptape_cloud_client.py b/griptape/tools/base_griptape_cloud_client.py index 8c42f817e..3e7f44fe6 100644 --- a/griptape/tools/base_griptape_cloud_client.py +++ b/griptape/tools/base_griptape_cloud_client.py @@ -6,7 +6,8 @@ @define class BaseGriptapeCloudClient(BaseTool, ABC): - """ + """Base class for Griptape Cloud clients. + Attributes: base_url: Base URL for the Griptape Cloud Knowledge Base API. api_key: API key for Griptape Cloud. diff --git a/griptape/tools/email_client/tool.py b/griptape/tools/email_client/tool.py index e2b42ea7e..6e0b32dc3 100644 --- a/griptape/tools/email_client/tool.py +++ b/griptape/tools/email_client/tool.py @@ -14,7 +14,7 @@ @define class EmailClient(BaseTool): - """Tool for working with email + """Tool for working with email. Attributes: username: Username/email address used to send email via the SMTP protocol and retrieve email via the IMAP protocol. diff --git a/griptape/tools/file_manager/tool.py b/griptape/tools/file_manager/tool.py index 162b546a6..e26ad7b3a 100644 --- a/griptape/tools/file_manager/tool.py +++ b/griptape/tools/file_manager/tool.py @@ -10,8 +10,7 @@ @define class FileManager(BaseTool): - """ - FileManager is a tool that can be used to list, load, and save files. + """FileManager is a tool that can be used to list, load, and save files. Attributes: file_manager_driver: File Manager Driver to use to list, load, and save files. diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 7c94cda5d..281c13b60 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -10,7 +10,8 @@ @define class GriptapeCloudKnowledgeBaseClient(BaseGriptapeCloudClient): - """ + """Tool for querying a Griptape Cloud Knowledge Base. + Attributes: description: LLM-friendly knowledge base description. knowledge_base_id: ID of the Griptape Cloud Knowledge Base. diff --git a/griptape/tools/rag_client/tool.py b/griptape/tools/rag_client/tool.py index 034843798..36ab82bf3 100644 --- a/griptape/tools/rag_client/tool.py +++ b/griptape/tools/rag_client/tool.py @@ -12,7 +12,8 @@ @define(kw_only=True) class RagClient(BaseTool): - """ + """Tool for querying a RAG engine. + Attributes: description: LLM-friendly RAG engine description. rag_engine: `RagEngine`. diff --git a/griptape/tools/rest_api_client/tool.py b/griptape/tools/rest_api_client/tool.py index e33971cc2..2722356e2 100644 --- a/griptape/tools/rest_api_client/tool.py +++ b/griptape/tools/rest_api_client/tool.py @@ -11,7 +11,8 @@ @define class RestApiClient(BaseTool): - """ + """A tool for making REST API requests. + Attributes: base_url: The base url that will be used for the request. path: The resource path that will be appended to base_url. diff --git a/griptape/tools/structure_run_client/tool.py b/griptape/tools/structure_run_client/tool.py index fe6d33f85..90b6071f1 100644 --- a/griptape/tools/structure_run_client/tool.py +++ b/griptape/tools/structure_run_client/tool.py @@ -14,7 +14,8 @@ @define class StructureRunClient(BaseTool): - """ + """Tool for running a Structure. + Attributes: description: A description of what the Structure does. driver: Driver to run the Structure. diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index a1d7463a7..8a334c21a 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -13,7 +13,8 @@ @define(kw_only=True) class VectorStoreClient(BaseTool): - """ + """A tool for querying a vector database. + Attributes: description: LLM-friendly vector DB description. vector_store_driver: `BaseVectorStoreDriver`. diff --git a/griptape/utils/dict_utils.py b/griptape/utils/dict_utils.py index 42214a895..e142d3bb2 100644 --- a/griptape/utils/dict_utils.py +++ b/griptape/utils/dict_utils.py @@ -16,7 +16,9 @@ def remove_key_in_dict_recursively(d: dict, key: str) -> dict: def dict_merge(dct: Optional[dict], merge_dct: Optional[dict], add_keys: bool = True) -> dict: - """Recursive dict merge. Inspired by :meth:``dict.update()``, instead of + """Recursive dict merge. + + Inspired by :meth:``dict.update()``, instead of updating only top-level keys, dict_merge recurses down into dicts nested to an arbitrary depth, updating keys. The ``merge_dct`` is merged into ``dct``. diff --git a/griptape/utils/file_utils.py b/griptape/utils/file_utils.py index ebe5ba456..daf2982d8 100644 --- a/griptape/utils/file_utils.py +++ b/griptape/utils/file_utils.py @@ -26,7 +26,6 @@ def load_files(paths: list[str], futures_executor: Optional[futures.ThreadPoolEx Returns: A dictionary where the keys are a hash of the path and the values are the content of the files. """ - if futures_executor is None: futures_executor = futures.ThreadPoolExecutor() diff --git a/griptape/utils/import_utils.py b/griptape/utils/import_utils.py index 0de09b2d1..b3e830caf 100644 --- a/griptape/utils/import_utils.py +++ b/griptape/utils/import_utils.py @@ -18,11 +18,11 @@ def import_optional_dependency(name: str) -> Optional[ModuleType]: Args: name: The module name. + Returns: The imported module, when found. None is returned when the package is not found and `errors` is False. """ - package_name = INSTALL_MAPPING.get(name) install_name = package_name if package_name is not None else name @@ -43,6 +43,7 @@ def is_dependency_installed(name: str) -> bool: Args: name: The module name. + Returns: True if the dependency is available. False if the dependency is not available. diff --git a/griptape/utils/structure_visualizer.py b/griptape/utils/structure_visualizer.py index 2a159a282..7c315a0bc 100644 --- a/griptape/utils/structure_visualizer.py +++ b/griptape/utils/structure_visualizer.py @@ -12,14 +12,15 @@ @define class StructureVisualizer: - """Utility class to visualize a Structure structure""" + """Utility class to visualize a Structure structure.""" structure: Structure = field() header: str = field(default="graph TD;", kw_only=True) def to_url(self) -> str: - """Generates a url that renders the Workflow structure as a Mermaid flowchart - Reference: https://mermaid.js.org/ecosystem/tutorials#jupyter-integration-with-mermaid-js + """Generates a url that renders the Workflow structure as a Mermaid flowchart. + + Reference: https://mermaid.js.org/ecosystem/tutorials#jupyter-integration-with-mermaid-js. Returns: str: URL to the rendered image diff --git a/pyproject.toml b/pyproject.toml index e2c4fdfd4..81a21946c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -209,7 +209,8 @@ select = [ "SIM", # flake8-simplify "TID251", # banned-api "T201", # print - "TCH" + "TCH", # flake8-type-checking + "D" # pydocstyle ] ignore = [ "UP007", # non-pep604-annotation @@ -217,7 +218,17 @@ ignore = [ "B024", # abstract-base-class-without-abstract-method "B009", # get-attr-with-constant "B010", # set-attr-with-constant + "D100", # undocumented-public-module + "D101", # undocumented-public-class + "D102", # undocumented-public-method + "D103", # undocumented-public-function + "D104", # undocumented-public-package + "D105", # undocumented-magic-method + "D106", # undocumented-public-nested-class + "D107", # undocumented-public-init ] +[tool.ruff.lint.pydocstyle] +convention = "google" [tool.ruff.lint.flake8-tidy-imports.banned-api] "attr".msg = "The attr module is deprecated, use attrs instead." From 2056f0e0c8491e2ee1a06bd9ea1143e57f7edcd7 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 11 Jul 2024 11:09:01 -0700 Subject: [PATCH 56/87] Add ruff rule for complex code paths (#951) --- griptape/chunkers/base_chunker.py | 29 ++++---- ...diffusion_image_generation_model_driver.py | 29 +++----- griptape/drivers/prompt/base_prompt_driver.py | 7 +- griptape/structures/workflow.py | 69 +++++++++++-------- griptape/tokenizers/openai_tokenizer.py | 2 +- pyproject.toml | 1 + 6 files changed, 77 insertions(+), 60 deletions(-) diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index 26199a16c..183264bb4 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -43,10 +43,9 @@ def _chunk_recursively(self, chunk: str, current_separator: Optional[ChunkSepara half_token_count = token_count // 2 # If a separator is provided, only use separators after it. - if current_separator: - separators = self.separators[self.separators.index(current_separator) :] - else: - separators = self.separators + separators = ( + self.separators[self.separators.index(current_separator) :] if current_separator else self.separators + ) # Loop through available separators to find the best split. for separator in separators: @@ -68,14 +67,7 @@ def _chunk_recursively(self, chunk: str, current_separator: Optional[ChunkSepara balance_diff = abs(tokens_count - half_token_count) # Create the two subchunks based on the best separator. - if separator.is_prefix: - # If the separator is a prefix, append it before this subchunk. - first_subchunk = separator.value + separator.value.join(subchunks[: balance_index + 1]) - second_subchunk = separator.value + separator.value.join(subchunks[balance_index + 1 :]) - else: - # If the separator is not a prefix, append it after this subchunk. - first_subchunk = separator.value.join(subchunks[: balance_index + 1]) + separator.value - second_subchunk = separator.value.join(subchunks[balance_index + 1 :]) + first_subchunk, second_subchunk = self.__get_subchunks(separator, subchunks, balance_index) # Continue recursively chunking the subchunks. first_subchunk_rec = self._chunk_recursively(first_subchunk.strip(), separator) @@ -94,3 +86,16 @@ def _chunk_recursively(self, chunk: str, current_separator: Optional[ChunkSepara # If none of the separators result in a balanced split, split the chunk in half. midpoint = len(chunk) // 2 return self._chunk_recursively(chunk[:midpoint]) + self._chunk_recursively(chunk[midpoint:]) + + def __get_subchunks(self, separator: ChunkSeparator, subchunks: list[str], balance_index: int) -> tuple[str, str]: + # Create the two subchunks based on the best separator. + if separator.is_prefix: + # If the separator is a prefix, append it before this subchunk. + first_subchunk = separator.value + separator.value.join(subchunks[: balance_index + 1]) + second_subchunk = separator.value + separator.value.join(subchunks[balance_index + 1 :]) + else: + # If the separator is not a prefix, append it after this subchunk. + first_subchunk = separator.value.join(subchunks[: balance_index + 1]) + separator.value + second_subchunk = separator.value.join(subchunks[balance_index + 1 :]) + + return first_subchunk, second_subchunk diff --git a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py index 9be3cc6b9..c0206dea0 100644 --- a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py @@ -109,16 +109,16 @@ def _request_parameters( text_prompts = [{"text": prompt, "weight": 1.0} for prompt in prompts] text_prompts += [{"text": negative_prompt, "weight": -1.0} for negative_prompt in negative_prompts] - request = {"text_prompts": text_prompts, "cfg_scale": self.cfg_scale} - - if self.style_preset is not None: - request["style_preset"] = self.style_preset - - if self.clip_guidance_preset is not None: - request["clip_guidance_preset"] = self.clip_guidance_preset - - if self.sampler is not None: - request["sampler"] = self.sampler + request = { + "text_prompts": text_prompts, + "cfg_scale": self.cfg_scale, + "style_preset": self.style_preset, + "clip_guidance_preset": self.clip_guidance_preset, + "sampler": self.sampler, + "steps": self.steps, + "seed": seed, + "start_schedule": self.start_schedule, + } if image is not None: request["init_image"] = image.base64 @@ -128,12 +128,6 @@ def _request_parameters( request["width"] = width request["height"] = height - if self.steps is not None: - request["steps"] = self.steps - - if seed is not None: - request["seed"] = seed - if mask is not None: if not mask_source: raise ValueError("mask_source must be provided when mask is provided") @@ -141,8 +135,7 @@ def _request_parameters( request["mask_source"] = mask_source request["mask_image"] = mask.base64 - if self.start_schedule is not None: - request["start_schedule"] = self.start_schedule + request = {k: v for k, v in request.items() if v is not None} return request diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index f012e7339..7a5c0cfc1 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -138,8 +138,13 @@ def __process_stream(self, prompt_stack: PromptStack) -> Message: self.structure.publish_event(CompletionChunkEvent(token=content.partial_input)) # Build a complete content from the content deltas + result = self.__build_message(list(delta_contents.values()), usage) + + return result + + def __build_message(self, delta_contents: list[list[BaseDeltaMessageContent]], usage: DeltaMessage.Usage): content = [] - for delta_content in delta_contents.values(): + for delta_content in delta_contents: text_deltas = [delta for delta in delta_content if isinstance(delta, TextDeltaMessageContent)] action_deltas = [delta for delta in delta_content if isinstance(delta, ActionCallDeltaMessageContent)] diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 3c0ee6586..523e5317d 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -64,37 +64,12 @@ def insert_task( ) -> BaseTask: task.preprocess(self) - for child_task in child_tasks: - # Link the new task to the child task - if child_task.id not in task.child_ids: - task.child_ids.append(child_task.id) - if task.id not in child_task.parent_ids: - child_task.parent_ids.append(task.id) + self.__link_task_to_children(task, child_tasks) if not preserve_relationship: - for parent_task in parent_tasks: - for child_task in child_tasks: - # Remove the old parent/child relationship - if child_task.id in parent_task.child_ids: - parent_task.child_ids.remove(child_task.id) - if parent_task.id in child_task.parent_ids: - child_task.parent_ids.remove(parent_task.id) + self.__remove_old_parent_child_relationships(parent_tasks, child_tasks) - last_parent_index = -1 - for parent_task in parent_tasks: - # Link the new task to the parent task - if parent_task.id not in task.parent_ids: - task.parent_ids.append(parent_task.id) - if task.id not in parent_task.child_ids: - parent_task.child_ids.append(task.id) - - try: - parent_index = self.tasks.index(parent_task) - except ValueError as exc: - raise ValueError(f"Parent task {parent_task.id} not found in workflow.") from exc - else: - if parent_index > last_parent_index: - last_parent_index = parent_index + last_parent_index = self.__link_task_to_parents(task, parent_tasks) # Insert the new task once, just after the last parent task self.tasks.insert(last_parent_index + 1, task) @@ -155,3 +130,41 @@ def to_graph(self) -> dict[str, set[str]]: def order_tasks(self) -> list[BaseTask]: return [self.find_task(task_id) for task_id in TopologicalSorter(self.to_graph()).static_order()] + + def __link_task_to_children(self, task: BaseTask, child_tasks: list[BaseTask]) -> None: + for child_task in child_tasks: + # Link the new task to the child task + if child_task.id not in task.child_ids: + task.child_ids.append(child_task.id) + if task.id not in child_task.parent_ids: + child_task.parent_ids.append(task.id) + + def __remove_old_parent_child_relationships( + self, parent_tasks: list[BaseTask], child_tasks: list[BaseTask] + ) -> None: + for parent_task in parent_tasks: + for child_task in child_tasks: + # Remove the old parent/child relationship + if child_task.id in parent_task.child_ids: + parent_task.child_ids.remove(child_task.id) + if parent_task.id in child_task.parent_ids: + child_task.parent_ids.remove(parent_task.id) + + def __link_task_to_parents(self, task: BaseTask, parent_tasks: list[BaseTask]) -> int: + last_parent_index = -1 + for parent_task in parent_tasks: + # Link the new task to the parent task + if parent_task.id not in task.parent_ids: + task.parent_ids.append(parent_task.id) + if task.id not in parent_task.child_ids: + parent_task.child_ids.append(task.id) + + try: + parent_index = self.tasks.index(parent_task) + except ValueError as exc: + raise ValueError(f"Parent task {parent_task.id} not found in workflow.") from exc + else: + if parent_index > last_parent_index: + last_parent_index = parent_index + + return last_parent_index diff --git a/griptape/tokenizers/openai_tokenizer.py b/griptape/tokenizers/openai_tokenizer.py index 3cb2674cf..13449f007 100644 --- a/griptape/tokenizers/openai_tokenizer.py +++ b/griptape/tokenizers/openai_tokenizer.py @@ -74,7 +74,7 @@ def _default_max_output_tokens(self) -> int: else: return tokens - def count_tokens(self, text: str | list[dict], model: Optional[str] = None) -> int: + def count_tokens(self, text: str | list[dict], model: Optional[str] = None) -> int: # noqa: C901 """Handles the special case of ChatML. Implementation adopted from the official OpenAI notebook: diff --git a/pyproject.toml b/pyproject.toml index 81a21946c..49e786a1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -209,6 +209,7 @@ select = [ "SIM", # flake8-simplify "TID251", # banned-api "T201", # print + "C901", # complex-structure "TCH", # flake8-type-checking "D" # pydocstyle ] From 627081ef4a2c727ed3b1fc3a09872dd6669d1889 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 11 Jul 2024 12:34:35 -0700 Subject: [PATCH 57/87] Add docs for OpenAI compatible services (#962) --- .../drivers/embedding-drivers.md | 22 +++++++++++++++ .../drivers/prompt-drivers.md | 27 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/docs/griptape-framework/drivers/embedding-drivers.md b/docs/griptape-framework/drivers/embedding-drivers.md index a607b0950..5bbad3e1e 100644 --- a/docs/griptape-framework/drivers/embedding-drivers.md +++ b/docs/griptape-framework/drivers/embedding-drivers.md @@ -27,6 +27,28 @@ print(embeddings[:3]) [0.0017853748286142945, 0.006118456833064556, -0.005811543669551611] ``` +### OpenAI Compatible + +Many services such as [LMStudio](https://lmstudio.ai/) and [OhMyGPT](https://www.ohmygpt.com/) provide OpenAI-compatible APIs. You can use the [OpenAiEmbeddingDriver](../../reference/griptape/drivers/embedding/openai_embedding_driver.md) to interact with these services. +Simply set the `base_url` to the service's API endpoint and the `model` to the model name. If the service requires an API key, you can set it in the `api_key` field. + +```python title="PYTEST_IGNORE" +from griptape.drivers import OpenAiEmbeddingDriver + +embedding_driver = OpenAiEmbeddingDriver( + base_url="http://127.0.0.1:1234/v1", + model="nomic-ai/nomic-embed-text-v1.5-GGUF/nomic-embed-text-v1.5.Q2_K", +) + +embeddings = embedding_driver.embed_string("Hello world!") + +# display the first 3 embeddings +print(embeddings[:3]) +``` + +!!! tip + Make sure to include `v1` at the end of the `base_url` to match the OpenAI API endpoint. + ### Azure OpenAI The [AzureOpenAiEmbeddingDriver](../../reference/griptape/drivers/embedding/azure_openai_embedding_driver.md) uses the same parameters as [OpenAiEmbeddingDriver](../../reference/griptape/drivers/embedding/openai_embedding_driver.md) diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index cdb90aef5..b9fc7f161 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -97,6 +97,33 @@ agent.run("Blue sky at dusk.") !!! info `response_format` and `seed` are unique to the OpenAI Chat Prompt Driver and Azure OpenAi Chat Prompt Driver. +### OpenAI Compatible + +Many services such as [LMStudio](https://lmstudio.ai/) and [OhMyGPT](https://www.ohmygpt.com/) provide OpenAI-compatible APIs. You can use the [OpenAiChatPromptDriver](../../reference/griptape/drivers/prompt/openai_chat_prompt_driver.md) to interact with these services. +Simply set the `base_url` to the service's API endpoint and the `model` to the model name. If the service requires an API key, you can set it in the `api_key` field. + +```python title="PYTEST_IGNORE" +from griptape.structures import Agent +from griptape.drivers import OpenAiChatPromptDriver +from griptape.rules import Rule +from griptape.config import StructureConfig + +agent = Agent( + config=StructureConfig( + prompt_driver=OpenAiChatPromptDriver( + base_url="http://127.0.0.1:1234/v1", + model="lmstudio-community/Meta-Llama-3-8B-Instruct-GGUF", stream=True + ) + ), + rules=[Rule(value="You are a helpful coding assistant.")], +) + +agent.run("How do I init and update a git submodule?") +``` + +!!! tip + Make sure to include `v1` at the end of the `base_url` to match the OpenAI API endpoint. + ### Azure OpenAI Chat !!! info From be9ce34c8a391dc08e26b900767d6f8c1002ccd4 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 11 Jul 2024 14:00:04 -0700 Subject: [PATCH 58/87] Native Tool Fixes (#963) --- .../official-tools/rag-client.md | 46 +++++++++---------- .../prompt/amazon_bedrock_prompt_driver.py | 2 +- .../drivers/prompt/anthropic_prompt_driver.py | 2 +- .../drivers/prompt/cohere_prompt_driver.py | 2 +- .../drivers/prompt/google_prompt_driver.py | 2 +- .../prompt/openai_chat_prompt_driver.py | 2 +- griptape/tasks/actions_subtask.py | 8 +++- griptape/tools/base_tool.py | 14 ++++++ griptape/tools/file_manager/tool.py | 2 +- griptape/tools/google_cal/tool.py | 2 +- griptape/tools/rest_api_client/tool.py | 6 +-- griptape/tools/structure_run_client/tool.py | 2 +- tests/unit/tools/test_base_tool.py | 9 ++++ 13 files changed, 63 insertions(+), 36 deletions(-) diff --git a/docs/griptape-tools/official-tools/rag-client.md b/docs/griptape-tools/official-tools/rag-client.md index b11287b3e..8b1447768 100644 --- a/docs/griptape-tools/official-tools/rag-client.md +++ b/docs/griptape-tools/official-tools/rag-client.md @@ -52,27 +52,25 @@ agent.run("what is Griptape?") ``` ``` -[07/11/24 08:47:04] INFO ToolkitTask 4a5308b86cac447783e6abe1be0646cd - Input: what is Griptape? -[07/11/24 08:47:06] INFO Subtask e034a5d82658411694e9e19e51fa6699 - Thought: I need to search for information about - Griptape using the RagClient. I will perform a - search query to gather relevant details. - - Actions: - [{"name":"RagClient","path":"search","input":{"valu - es":{"query":"What is - Griptape?"}},"tag":"search_griptape"}] -[07/11/24 08:47:08] INFO Subtask e034a5d82658411694e9e19e51fa6699 - Response: Griptape builds AI-powered applications - that connect securely to your enterprise data and - APIs. Griptape Agents provide incredible power and - flexibility when working with large language - models. -[07/11/24 08:47:09] INFO ToolkitTask 4a5308b86cac447783e6abe1be0646cd - Output: Griptape builds AI-powered applications - that connect securely to your enterprise data and - APIs. Griptape Agents provide incredible power and - flexibility when working with large language - models. -``` \ No newline at end of file +[07/11/24 13:30:43] INFO ToolkitTask a6d057d5c71d4e9cb6863a2adb64b76c + Input: what is Griptape? +[07/11/24 13:30:44] INFO Subtask 8fd89ed9eefe49b8892187f2fca3890a + Actions: [ + { + "tag": "call_4MaDzOuKnWAs2gmhK3KJhtjI", + "name": "RagClient", + "path": "search", + "input": { + "values": { + "query": "What is Griptape?" + } + } + } + ] +[07/11/24 13:30:49] INFO Subtask 8fd89ed9eefe49b8892187f2fca3890a + Response: Griptape builds AI-powered applications that connect securely to your enterprise data and APIs. Griptape Agents provide incredible + power and flexibility when working with large language models. + INFO ToolkitTask a6d057d5c71d4e9cb6863a2adb64b76c + Output: Griptape builds AI-powered applications that connect securely to your enterprise data and APIs. Griptape Agents provide incredible + power and flexibility when working with large language models. +``` diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 5158740df..0b56af445 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -117,7 +117,7 @@ def __to_bedrock_tools(self, tools: list[BaseTool]) -> list[dict]: return [ { "toolSpec": { - "name": f"{tool.name}_{tool.activity_name(activity)}", + "name": tool.to_native_tool_name(activity), "description": tool.activity_description(activity), "inputSchema": { "json": (tool.activity_schema(activity) or Schema({})).json_schema( diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 877e41621..d42fee46f 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -124,7 +124,7 @@ def __to_anthropic_role(self, message: Message) -> str: def __to_anthropic_tools(self, tools: list[BaseTool]) -> list[dict]: return [ { - "name": f"{tool.name}_{tool.activity_name(activity)}", + "name": tool.to_native_tool_name(activity), "description": tool.activity_description(activity), "input_schema": (tool.activity_schema(activity) or Schema({})).json_schema("Input Schema"), } diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index a5dccb2a5..3943e2211 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -181,7 +181,7 @@ def __to_cohere_tools(self, tools: list[BaseTool]) -> list[dict]: tool_definitions.append( { - "name": f"{tool.name}_{tool.activity_name(activity)}", + "name": tool.to_native_tool_name(activity), "description": tool.activity_description(activity), "parameter_definitions": { property_name: { diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 48bb29f59..02b9f0f87 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -177,7 +177,7 @@ def __to_google_tools(self, tools: list[BaseTool]) -> list[dict]: schema = remove_key_in_dict_recursively(schema, "additionalProperties") tool_declaration = FunctionDeclaration( - name=f"{tool.name}_{tool.activity_name(activity)}", + name=tool.to_native_tool_name(activity), description=tool.activity_description(activity), parameters={ "type": schema["type"], diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index c6bd02489..b706cbeb6 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -210,7 +210,7 @@ def __to_openai_tools(self, tools: list[BaseTool]) -> list[dict]: return [ { "function": { - "name": f"{tool.name}_{tool.activity_name(activity)}", + "name": tool.to_native_tool_name(activity), "description": tool.activity_description(activity), "parameters": (tool.activity_schema(activity) or Schema({})).json_schema("Parameters Schema"), }, diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index ac0503e8f..ba73a29f0 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -89,7 +89,13 @@ def before_run(self) -> None: subtask_actions=self.actions_to_dicts(), ) ) - self.structure.logger.info(f"Subtask {self.id}\n{self.actions_to_json()}") + + parts = [ + f"Subtask {self.id}", + *([f"\nThought: {self.thought}"] if self.thought is not None else []), + f"\nActions: {self.actions_to_json()}", + ] + self.structure.logger.info("".join(parts)) def run(self) -> BaseArtifact: try: diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index c46027049..317a95ad5 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -187,3 +187,17 @@ def find_input_memory(self, memory_name: str) -> Optional[TaskMemory]: return next((m for m in self.input_memory if m.name == memory_name), None) else: return None + + def to_native_tool_name(self, activity: Callable) -> str: + """Converts a Tool into to a native tool name. + + Args: + activity: Activity to convert. + + Returns: + str: Native tool name. + """ + if "_" in self.name: + raise ValueError("Tool name can't contain underscores when using native tools.") + + return f"{self.name}_{self.activity_name(activity)}" diff --git a/griptape/tools/file_manager/tool.py b/griptape/tools/file_manager/tool.py index e26ad7b3a..47582f8cc 100644 --- a/griptape/tools/file_manager/tool.py +++ b/griptape/tools/file_manager/tool.py @@ -38,7 +38,7 @@ def list_files_from_disk(self, params: dict) -> TextArtifact | ErrorArtifact: Literal( "paths", description="Relative paths to files to be loaded in the POSIX format. For example, ['foo/bar/file.txt']", - ): list + ): list[str] } ), } diff --git a/griptape/tools/google_cal/tool.py b/griptape/tools/google_cal/tool.py index b18c5f41c..e0097fd02 100644 --- a/griptape/tools/google_cal/tool.py +++ b/griptape/tools/google_cal/tool.py @@ -86,7 +86,7 @@ def get_upcoming_events(self, params: dict) -> ListArtifact | ErrorArtifact: Literal("description", description="description of the event"): str, Literal( "attendees", description="list of the email addresses of attendees using 'email' as key" - ): list, + ): list[str], Optional(Literal("location", description="location of the event")): str, } ), diff --git a/griptape/tools/rest_api_client/tool.py b/griptape/tools/rest_api_client/tool.py index 2722356e2..6206c1dba 100644 --- a/griptape/tools/rest_api_client/tool.py +++ b/griptape/tools/rest_api_client/tool.py @@ -79,7 +79,7 @@ def put(self, params: dict) -> BaseArtifact: ), "schema": Schema( { - Literal("path_params", description="The request path parameters."): list, + Literal("path_params", description="The request path parameters."): list[str], Literal("body", description="The request body."): dict, } ), @@ -144,7 +144,7 @@ def post(self, params: dict) -> BaseArtifact: Schema( { schema.Optional(Literal("query_params", description="The request query parameters.")): dict, - schema.Optional(Literal("path_params", description="The request path parameters.")): list, + schema.Optional(Literal("path_params", description="The request path parameters.")): list[str], } ) ), @@ -183,7 +183,7 @@ def get(self, params: dict) -> BaseArtifact: "schema": Schema( { schema.Optional(Literal("query_params", description="The request query parameters.")): dict, - schema.Optional(Literal("path_params", description="The request path parameters.")): list, + schema.Optional(Literal("path_params", description="The request path parameters.")): list[str], } ), } diff --git a/griptape/tools/structure_run_client/tool.py b/griptape/tools/structure_run_client/tool.py index 90b6071f1..79ed635df 100644 --- a/griptape/tools/structure_run_client/tool.py +++ b/griptape/tools/structure_run_client/tool.py @@ -28,7 +28,7 @@ class StructureRunClient(BaseTool): config={ "description": "Can be used to run a Griptape Structure with the following description: {{ self.description }}", "schema": Schema( - {Literal("args", description="A list of string arguments to submit to the Structure Run"): list} + {Literal("args", description="A list of string arguments to submit to the Structure Run"): list[str]} ), } ) diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index 4b9b97260..51d76d3fd 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -223,3 +223,12 @@ def test_activity_schemas(self, tool): tool_schema = full_schema.json_schema(f"{tool.name} ToolAction Schema") assert tool_schema == self.TARGET_TOOL_SCHEMA + + def test_to_native_tool_name(self, tool): + tool = MockTool() + + assert tool.to_native_tool_name(tool.test) == "MockTool_test" + + with pytest.raises(ValueError): + tool.name = "mock_tool" + tool.to_native_tool_name(tool.foo) From afb8ceac7e0555cd0d07cd80cd97a63a3fcca643 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Fri, 12 Jul 2024 09:34:18 -0700 Subject: [PATCH 59/87] Catch tool errors (#965) --- griptape/tools/base_tool.py | 15 ++++++---- tests/mocks/mock_tool/tool.py | 9 ++++++ .../test_amazon_bedrock_prompt_driver.py | 23 ++++++++++++++ .../prompt/test_anthropic_prompt_driver.py | 19 ++++++++++++ .../prompt/test_cohere_prompt_driver.py | 5 ++++ .../prompt/test_google_prompt_driver.py | 5 ++++ .../prompt/test_openai_chat_prompt_driver.py | 22 ++++++++++++++ tests/unit/mixins/test_activity_mixin.py | 4 +-- tests/unit/tasks/test_actions_subtask.py | 30 +++++++++++++++++++ tests/unit/tasks/test_tool_task.py | 24 +++++++++++++++ tests/unit/tasks/test_toolkit_task.py | 24 +++++++++++++++ tests/unit/tools/test_base_tool.py | 23 ++++++++++++++ 12 files changed, 196 insertions(+), 7 deletions(-) diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 317a95ad5..bfff2fffb 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -10,7 +10,7 @@ from typing import Optional import yaml from attrs import define, field, Factory -from griptape.artifacts import BaseArtifact, InfoArtifact, TextArtifact +from griptape.artifacts import BaseArtifact, InfoArtifact, TextArtifact, ErrorArtifact from griptape.mixins import ActivityMixin if TYPE_CHECKING: @@ -105,11 +105,16 @@ def activity_schemas(self) -> list[Schema]: ] def execute(self, activity: Callable, subtask: ActionsSubtask, action: ToolAction) -> BaseArtifact: - preprocessed_input = self.before_run(activity, subtask, action) - output = self.run(activity, subtask, action, preprocessed_input) - postprocessed_output = self.after_run(activity, subtask, action, output) + try: + output = self.before_run(activity, subtask, action) - return postprocessed_output + output = self.run(activity, subtask, action, output) + + output = self.after_run(activity, subtask, action, output) + except Exception as e: + output = ErrorArtifact(str(e), exception=e) + + return output def before_run(self, activity: Callable, subtask: ActionsSubtask, action: ToolAction) -> Optional[dict]: return action.input diff --git a/tests/mocks/mock_tool/tool.py b/tests/mocks/mock_tool/tool.py index 266f77c1b..e79023a6e 100644 --- a/tests/mocks/mock_tool/tool.py +++ b/tests/mocks/mock_tool/tool.py @@ -29,6 +29,15 @@ def test(self, value: dict) -> BaseArtifact: def test_error(self, value: dict) -> BaseArtifact: return ErrorArtifact(f"error {value['values']['test']}") + @activity( + config={ + "description": "test description: {{ _self.foo() }}", + "schema": Schema({Literal("test"): str}, description="Test input"), + } + ) + def test_exception(self, value: dict) -> BaseArtifact: + raise Exception(f"error {value['values']['test']}") + @activity( config={ "description": "test description: {{ _self.foo() }}", diff --git a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py index 4b8323969..e31b6a448 100644 --- a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py @@ -56,6 +56,29 @@ class TestAmazonBedrockPromptDriver: "name": "MockTool_test_error", } }, + { + "toolSpec": { + "description": "test description: foo", + "inputSchema": { + "json": { + "$id": "http://json-schema.org/draft-07/schema#", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + } + }, + "name": "MockTool_test_exception", + } + }, { "toolSpec": { "description": "test description", diff --git a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py index 67b3af372..e8f6d337f 100644 --- a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py @@ -48,6 +48,25 @@ class TestAnthropicPromptDriver: }, "name": "MockTool_test_error", }, + { + "description": "test description: foo", + "input_schema": { + "$id": "Input Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + "name": "MockTool_test_exception", + }, { "description": "test description", "input_schema": { diff --git a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py index 059aaffe5..167c08b34 100644 --- a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py @@ -23,6 +23,11 @@ class TestCoherePromptDriver: "name": "MockTool_test_error", "parameter_definitions": {"test": {"required": True, "type": "string"}}, }, + { + "description": "test description: foo", + "name": "MockTool_test_exception", + "parameter_definitions": {"test": {"required": True, "type": "string"}}, + }, {"description": "test description", "name": "MockTool_test_list_output", "parameter_definitions": {}}, {"description": "test description", "name": "MockTool_test_no_schema", "parameter_definitions": {}}, { diff --git a/tests/unit/drivers/prompt/test_google_prompt_driver.py b/tests/unit/drivers/prompt/test_google_prompt_driver.py index c4b341481..b1a72d10d 100644 --- a/tests/unit/drivers/prompt/test_google_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_google_prompt_driver.py @@ -24,6 +24,11 @@ class TestGooglePromptDriver: "description": "test description: foo", "parameters": {"type": "OBJECT", "properties": {"test": {"type": "STRING"}}, "required": ["test"]}, }, + { + "name": "MockTool_test_exception", + "description": "test description: foo", + "parameters": {"type": "OBJECT", "properties": {"test": {"type": "STRING"}}, "required": ["test"]}, + }, {"name": "MockTool_test_list_output", "description": "test description", "parameters": {"type": "OBJECT"}}, {"name": "MockTool_test_no_schema", "description": "test description", "parameters": {"type": "OBJECT"}}, { diff --git a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py index 9e664a398..59772ff23 100644 --- a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py @@ -55,6 +55,28 @@ class TestOpenAiChatPromptDriverFixtureMixin: }, "type": "function", }, + { + "function": { + "description": "test description: foo", + "name": "MockTool_test_exception", + "parameters": { + "$id": "Parameters Schema", + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": False, + "properties": { + "values": { + "additionalProperties": False, + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "type": "object", + } + }, + "required": ["values"], + "type": "object", + }, + }, + "type": "function", + }, { "function": { "description": "test description", diff --git a/tests/unit/mixins/test_activity_mixin.py b/tests/unit/mixins/test_activity_mixin.py index c27568c21..45db7cc7f 100644 --- a/tests/unit/mixins/test_activity_mixin.py +++ b/tests/unit/mixins/test_activity_mixin.py @@ -31,7 +31,7 @@ def test_find_activity(self): assert tool.find_activity("test_str_output") is None def test_activities(self, tool): - assert len(tool.activities()) == 6 + assert len(tool.activities()) == 7 assert tool.activities()[0] == tool.test def test_allowlist_and_denylist_validation(self): @@ -46,7 +46,7 @@ def test_allowlist(self): def test_denylist(self): tool = MockTool(test_field="hello", test_int=5, denylist=["test"]) - assert len(tool.activities()) == 5 + assert len(tool.activities()) == 6 def test_invalid_allowlist(self): with pytest.raises(ValueError): diff --git a/tests/unit/tasks/test_actions_subtask.py b/tests/unit/tasks/test_actions_subtask.py index ede892e2d..c6e5ca038 100644 --- a/tests/unit/tasks/test_actions_subtask.py +++ b/tests/unit/tasks/test_actions_subtask.py @@ -162,3 +162,33 @@ def test_implicit_values(self): assert json_dict[0]["name"] == "MockTool" assert json_dict[0]["path"] == "test" assert json_dict[0]["input"] == {"values": {"test": "value"}} + + def test_execute_tool(self): + valid_input = ( + "Thought: need to test\n" + 'Actions:[{"tag": "foo", "name": "MockTool","path": "test","input": {"values": {"test": "value"}}}]' + ) + + task = ToolkitTask(tools=[MockTool()]) + Agent().add_task(task) + subtask = task.add_subtask(ActionsSubtask(valid_input)) + subtask.execute() + + assert isinstance(subtask.output, ListArtifact) + assert isinstance(subtask.output.value[0], TextArtifact) + assert subtask.output.value[0].value == "ack value" + + def test_execute_tool_exception(self): + valid_input = ( + "Thought: need to test\n" + 'Actions:[{"tag": "foo", "name": "MockTool","path": "test_exception","input": {"values": {"test": "value"}}}]' + ) + + task = ToolkitTask(tools=[MockTool()]) + Agent().add_task(task) + subtask = task.add_subtask(ActionsSubtask(valid_input)) + subtask.execute() + + assert isinstance(subtask.output, ListArtifact) + assert isinstance(subtask.output.value[0], ErrorArtifact) + assert subtask.output.value[0].value == "error value" diff --git a/tests/unit/tasks/test_tool_task.py b/tests/unit/tasks/test_tool_task.py index efab408fe..2af8b73c3 100644 --- a/tests/unit/tasks/test_tool_task.py +++ b/tests/unit/tasks/test_tool_task.py @@ -63,6 +63,30 @@ class TestToolTask: "required": ["name", "path", "input", "tag"], "additionalProperties": False, }, + { + "type": "object", + "properties": { + "name": {"const": "MockTool"}, + "path": {"description": "test description: foo", "const": "test_exception"}, + "input": { + "type": "object", + "properties": { + "values": { + "description": "Test input", + "type": "object", + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "additionalProperties": False, + } + }, + "required": ["values"], + "additionalProperties": False, + }, + "tag": {"description": "Unique tag name for action execution.", "type": "string"}, + }, + "required": ["name", "path", "input", "tag"], + "additionalProperties": False, + }, { "type": "object", "properties": { diff --git a/tests/unit/tasks/test_toolkit_task.py b/tests/unit/tasks/test_toolkit_task.py index 38002553c..2217ba70c 100644 --- a/tests/unit/tasks/test_toolkit_task.py +++ b/tests/unit/tasks/test_toolkit_task.py @@ -61,6 +61,30 @@ class TestToolkitSubtask: "required": ["name", "path", "input", "tag"], "additionalProperties": False, }, + { + "type": "object", + "properties": { + "name": {"const": "MockTool"}, + "path": {"description": "test description: foo", "const": "test_exception"}, + "input": { + "type": "object", + "properties": { + "values": { + "description": "Test input", + "type": "object", + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "additionalProperties": False, + } + }, + "required": ["values"], + "additionalProperties": False, + }, + "tag": {"description": "Unique tag name for action execution.", "type": "string"}, + }, + "required": ["name", "path", "input", "tag"], + "additionalProperties": False, + }, { "type": "object", "properties": { diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index 51d76d3fd..75154b509 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -59,6 +59,29 @@ class TestBaseTool: "required": ["name", "path", "input"], "additionalProperties": False, }, + { + "type": "object", + "properties": { + "name": {"const": "MockTool"}, + "path": {"description": "test description: foo", "const": "test_exception"}, + "input": { + "type": "object", + "properties": { + "values": { + "description": "Test input", + "type": "object", + "properties": {"test": {"type": "string"}}, + "required": ["test"], + "additionalProperties": False, + } + }, + "required": ["values"], + "additionalProperties": False, + }, + }, + "required": ["name", "path", "input"], + "additionalProperties": False, + }, { "type": "object", "properties": { From fe1e9915a665eea3ce2d161b74bb100350ca0e00 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Fri, 12 Jul 2024 12:16:56 -0700 Subject: [PATCH 60/87] Add isort ruff rule (#967) --- griptape/artifacts/action_artifact.py | 3 +- griptape/artifacts/base_artifact.py | 9 +++-- griptape/artifacts/blob_artifact.py | 5 ++- griptape/artifacts/boolean_artifact.py | 3 ++ griptape/artifacts/csv_row_artifact.py | 5 ++- griptape/artifacts/error_artifact.py | 3 ++ griptape/artifacts/info_artifact.py | 2 + griptape/artifacts/list_artifact.py | 6 ++- griptape/artifacts/media_artifact.py | 5 ++- griptape/artifacts/text_artifact.py | 3 ++ griptape/chunkers/base_chunker.py | 5 ++- griptape/common/actions/base_action.py | 3 +- griptape/common/actions/tool_action.py | 1 + .../action_call_delta_message_content.py | 4 +- .../contents/action_call_message_content.py | 5 +-- .../contents/action_result_message_content.py | 5 ++- .../contents/base_message_content.py | 6 ++- .../contents/image_message_content.py | 5 ++- .../contents/text_delta_message_content.py | 1 + .../contents/text_message_content.py | 5 ++- .../prompt_stack/messages/base_message.py | 6 +-- .../prompt_stack/messages/delta_message.py | 3 +- .../common/prompt_stack/messages/message.py | 2 +- griptape/common/reference.py | 4 +- .../config/amazon_bedrock_structure_config.py | 6 ++- .../config/azure_openai_structure_config.py | 5 ++- griptape/config/base_structure_config.py | 6 +-- griptape/config/cohere_structure_config.py | 4 +- griptape/config/openai_structure_config.py | 8 ++-- griptape/config/structure_config.py | 16 ++++---- .../base_audio_transcription_driver.py | 4 +- .../dummy_audio_transcription_driver.py | 1 + .../openai_audio_transcription_driver.py | 2 +- .../amazon_bedrock_cohere_embedding_driver.py | 10 +++-- .../amazon_bedrock_titan_embedding_driver.py | 10 +++-- ...on_sagemaker_jumpstart_embedding_driver.py | 4 +- .../azure_openai_embedding_driver.py | 6 ++- .../embedding/base_embedding_driver.py | 10 +++-- .../embedding/cohere_embedding_driver.py | 5 ++- .../embedding/dummy_embedding_driver.py | 1 + .../embedding/google_embedding_driver.py | 3 ++ .../huggingface_hub_embedding_driver.py | 7 +++- .../embedding/ollama_embedding_driver.py | 9 +++-- .../embedding/openai_embedding_driver.py | 7 +++- .../embedding/voyageai_embedding_driver.py | 9 +++-- .../base_event_listener_driver.py | 4 +- .../griptape_cloud_event_listener_driver.py | 6 +-- .../pusher_event_listener_driver.py | 4 +- .../webhook_event_listener_driver.py | 1 - .../amazon_s3_file_manager_driver.py | 6 ++- .../file_manager/base_file_manager_driver.py | 5 ++- .../file_manager/local_file_manager_driver.py | 5 ++- .../amazon_bedrock_image_generation_driver.py | 2 +- .../azure_openai_image_generation_driver.py | 5 ++- .../base_image_generation_driver.py | 2 +- ...ase_multi_model_image_generation_driver.py | 3 +- .../dummy_image_generation_driver.py | 2 + .../leonardo_image_generation_driver.py | 4 +- .../openai_image_generation_driver.py | 4 +- .../base_image_generation_model_driver.py | 2 +- ...diffusion_image_generation_model_driver.py | 4 +- ...ock_titan_image_generation_model_driver.py | 4 +- .../amazon_bedrock_image_query_driver.py | 10 +++-- .../anthropic_image_query_driver.py | 7 +++- .../azure_openai_image_query_driver.py | 3 +- .../image_query/base_image_query_driver.py | 8 ++-- .../base_multi_model_image_query_driver.py | 3 +- .../image_query/dummy_image_query_driver.py | 2 +- .../image_query/openai_image_query_driver.py | 8 ++-- .../base_image_query_model_driver.py | 7 +++- ...bedrock_claude_image_query_model_driver.py | 2 + ...zon_dynamodb_conversation_memory_driver.py | 9 +++-- .../base_conversation_memory_driver.py | 4 +- .../local_conversation_memory_driver.py | 4 +- .../redis_conversation_memory_driver.py | 7 +++- .../prompt/amazon_bedrock_prompt_driver.py | 1 + ...mazon_sagemaker_jumpstart_prompt_driver.py | 3 +- .../drivers/prompt/anthropic_prompt_driver.py | 9 +++-- .../prompt/azure_openai_chat_prompt_driver.py | 6 ++- griptape/drivers/prompt/base_prompt_driver.py | 9 +++-- .../drivers/prompt/cohere_prompt_driver.py | 23 ++++++----- .../drivers/prompt/dummy_prompt_driver.py | 6 ++- .../drivers/prompt/google_prompt_driver.py | 22 +++++------ .../prompt/huggingface_hub_prompt_driver.py | 3 +- .../huggingface_pipeline_prompt_driver.py | 3 +- .../drivers/prompt/ollama_prompt_driver.py | 21 +++++++--- .../prompt/openai_chat_prompt_driver.py | 9 +++-- griptape/drivers/rerank/base_rerank_driver.py | 2 + .../drivers/rerank/cohere_rerank_driver.py | 8 +++- .../drivers/sql/amazon_redshift_sql_driver.py | 7 +++- griptape/drivers/sql/base_sql_driver.py | 3 +- griptape/drivers/sql/snowflake_sql_driver.py | 11 ++++-- griptape/drivers/sql/sql_driver.py | 7 +++- .../base_structure_run_driver.py | 2 +- .../griptape_cloud_structure_run_driver.py | 2 +- .../local_structure_run_driver.py | 4 +- .../dummy_text_to_speech_driver.py | 1 + .../elevenlabs_text_to_speech_driver.py | 2 +- .../openai_text_to_speech_driver.py | 4 +- .../amazon_opensearch_vector_store_driver.py | 7 +++- .../azure_mongodb_vector_store_driver.py | 3 ++ .../vector/base_vector_store_driver.py | 10 +++-- .../vector/dummy_vector_store_driver.py | 6 ++- .../vector/local_vector_store_driver.py | 6 ++- .../vector/marqo_vector_store_driver.py | 12 ++++-- .../mongodb_atlas_vector_store_driver.py | 5 ++- .../vector/opensearch_vector_store_driver.py | 11 ++++-- .../vector/pgvector_vector_store_driver.py | 16 ++++---- .../vector/pinecone_vector_store_driver.py | 9 +++-- .../vector/qdrant_vector_store_driver.py | 7 +++- .../vector/redis_vector_store_driver.py | 9 +++-- .../markdownify_web_scraper_driver.py | 4 +- .../web_scraper/proxy_web_scraper_driver.py | 2 +- .../trafilatura_web_scraper_driver.py | 2 + .../web_search/base_web_search_driver.py | 3 +- .../duck_duck_go_web_search_driver.py | 7 +++- .../web_search/google_web_search_driver.py | 8 ++-- .../engines/audio/text_to_speech_engine.py | 6 +-- .../extraction/base_extraction_engine.py | 11 ++++-- .../extraction/csv_extraction_engine.py | 9 +++-- .../extraction/json_extraction_engine.py | 11 ++++-- .../image/base_image_generation_engine.py | 8 ++-- .../inpainting_image_generation_engine.py | 5 ++- .../outpainting_image_generation_engine.py | 3 +- .../image/prompt_image_generation_engine.py | 5 ++- .../variation_image_generation_engine.py | 5 ++- .../engines/rag/modules/base_rag_module.py | 8 ++-- .../modules/query/base_query_rag_module.py | 2 + .../base_after_response_rag_module.py | 2 + .../base_before_response_rag_module.py | 2 + .../response/base_response_rag_module.py | 2 + .../metadata_before_response_rag_module.py | 2 + .../response/prompt_response_rag_module.py | 4 +- .../rulesets_before_response_rag_module.py | 1 + .../text_chunks_response_rag_module.py | 1 + .../retrieval/base_rerank_rag_module.py | 3 +- .../retrieval/base_retrieval_rag_module.py | 4 +- .../text_chunks_rerank_rag_module.py | 3 +- .../text_loader_retrieval_rag_module.py | 10 +++-- .../vector_store_retrieval_rag_module.py | 8 +++- griptape/engines/rag/rag_context.py | 6 ++- griptape/engines/rag/rag_engine.py | 2 + griptape/engines/rag/stages/base_rag_stage.py | 4 +- .../engines/rag/stages/query_rag_stage.py | 2 + .../engines/rag/stages/response_rag_stage.py | 6 ++- .../engines/rag/stages/retrieval_rag_stage.py | 5 ++- .../engines/summary/base_summary_engine.py | 4 +- .../engines/summary/prompt_summary_engine.py | 8 ++-- griptape/events/base_actions_subtask_event.py | 5 ++- .../events/base_image_generation_event.py | 5 ++- .../events/base_media_generation_event.py | 5 ++- griptape/events/base_prompt_event.py | 5 ++- griptape/events/base_task_event.py | 7 +++- griptape/events/base_text_to_speech_event.py | 4 +- griptape/events/completion_chunk_event.py | 4 +- griptape/events/event_listener.py | 9 +++-- .../events/finish_actions_subtask_event.py | 2 + griptape/events/finish_prompt_event.py | 4 +- griptape/events/finish_task_event.py | 2 + .../events/start_actions_subtask_event.py | 2 + .../events/start_image_generation_event.py | 1 + griptape/events/start_prompt_event.py | 6 ++- griptape/events/start_task_event.py | 2 + griptape/loaders/base_loader.py | 5 ++- griptape/loaders/base_text_loader.py | 9 +++-- griptape/loaders/blob_loader.py | 1 + griptape/loaders/csv_loader.py | 3 +- griptape/loaders/dataframe_loader.py | 5 ++- griptape/loaders/email_loader.py | 6 +-- griptape/loaders/image_loader.py | 2 +- griptape/loaders/pdf_loader.py | 9 +++-- griptape/loaders/sql_loader.py | 2 +- griptape/loaders/text_loader.py | 4 +- griptape/loaders/web_loader.py | 7 +++- .../memory/meta/action_subtask_meta_entry.py | 5 ++- griptape/memory/meta/base_meta_entry.py | 4 +- griptape/memory/meta/meta_memory.py | 1 + .../structure/base_conversation_memory.py | 7 +++- .../memory/structure/conversation_memory.py | 7 +++- griptape/memory/structure/run.py | 4 +- .../structure/summary_conversation_memory.py | 9 +++-- .../task/storage/base_artifact_storage.py | 6 ++- .../task/storage/blob_artifact_storage.py | 4 +- .../task/storage/text_artifact_storage.py | 7 +++- griptape/memory/task/task_memory.py | 9 +++-- .../mixins/actions_subtask_origin_mixin.py | 8 ++-- griptape/mixins/activity_mixin.py | 7 ++-- griptape/mixins/exponential_backoff_mixin.py | 5 ++- .../media_artifact_file_output_mixin.py | 3 +- griptape/mixins/rule_mixin.py | 2 +- griptape/mixins/serializable_mixin.py | 6 +-- griptape/rules/rule.py | 1 + griptape/rules/ruleset.py | 3 +- griptape/schemas/base_schema.py | 38 ++++++++++--------- griptape/schemas/bytes_field.py | 3 +- griptape/schemas/polymorphic_schema.py | 4 +- griptape/structures/agent.py | 7 +++- griptape/structures/pipeline.py | 5 ++- griptape/structures/structure.py | 19 ++++++---- griptape/structures/workflow.py | 9 +++-- griptape/tasks/actions_subtask.py | 10 +++-- griptape/tasks/audio_transcription_task.py | 3 +- griptape/tasks/base_audio_generation_task.py | 2 +- griptape/tasks/base_image_generation_task.py | 8 ++-- griptape/tasks/base_multi_text_input_task.py | 2 +- griptape/tasks/base_task.py | 8 ++-- griptape/tasks/code_execution_task.py | 5 ++- griptape/tasks/csv_extraction_task.py | 2 + griptape/tasks/extraction_task.py | 7 +++- .../tasks/inpainting_image_generation_task.py | 2 +- griptape/tasks/json_extraction_task.py | 2 + .../outpainting_image_generation_task.py | 2 +- .../tasks/prompt_image_generation_task.py | 2 +- griptape/tasks/prompt_task.py | 5 +-- griptape/tasks/rag_task.py | 7 +++- griptape/tasks/structure_run_task.py | 4 +- griptape/tasks/text_summary_task.py | 3 ++ griptape/tasks/text_to_speech_task.py | 4 +- griptape/tasks/tool_task.py | 13 ++++--- griptape/tasks/toolkit_task.py | 14 ++++--- .../tasks/variation_image_generation_task.py | 2 +- .../tokenizers/amazon_bedrock_tokenizer.py | 1 + griptape/tokenizers/anthropic_tokenizer.py | 7 +++- griptape/tokenizers/base_tokenizer.py | 4 +- griptape/tokenizers/cohere_tokenizer.py | 3 ++ griptape/tokenizers/dummy_tokenizer.py | 5 ++- griptape/tokenizers/google_tokenizer.py | 7 +++- griptape/tokenizers/huggingface_tokenizer.py | 6 ++- griptape/tokenizers/simple_tokenizer.py | 2 + .../tools/audio_transcription_client/tool.py | 8 ++-- griptape/tools/aws_iam_client/tool.py | 11 ++++-- griptape/tools/aws_s3_client/tool.py | 13 ++++--- griptape/tools/base_aws_client.py | 7 +++- griptape/tools/base_google_client.py | 4 +- griptape/tools/base_griptape_cloud_client.py | 3 ++ griptape/tools/base_tool.py | 16 ++++---- griptape/tools/calculator/tool.py | 3 +- griptape/tools/computer/tool.py | 14 ++++--- griptape/tools/date_time/tool.py | 4 +- griptape/tools/email_client/tool.py | 15 +++++--- griptape/tools/file_manager/tool.py | 7 +++- griptape/tools/google_cal/tool.py | 11 ++++-- griptape/tools/google_docs/tool.py | 9 +++-- griptape/tools/google_drive/tool.py | 11 ++++-- griptape/tools/google_gmail/tool.py | 11 ++++-- .../tool.py | 9 +++-- griptape/tools/image_query_client/tool.py | 8 ++-- .../tool.py | 4 +- griptape/tools/openweather_client/tool.py | 15 +++++--- .../tool.py | 6 +-- .../prompt_image_generation_client/tool.py | 9 +++-- griptape/tools/rag_client/tool.py | 9 +++-- griptape/tools/rest_api_client/tool.py | 14 ++++--- griptape/tools/sql_client/tool.py | 9 +++-- griptape/tools/structure_run_client/tool.py | 3 +- griptape/tools/task_memory_client/tool.py | 6 ++- griptape/tools/text_to_speech_client/tool.py | 8 ++-- .../variation_image_generation_client/tool.py | 6 +-- griptape/tools/vector_store_client/tool.py | 12 +++--- griptape/tools/web_scraper/tool.py | 8 ++-- griptape/tools/web_search/tool.py | 7 +++- griptape/utils/command_runner.py | 4 +- griptape/utils/conversation.py | 2 + griptape/utils/decorators.py | 2 +- griptape/utils/file_utils.py | 3 +- griptape/utils/import_utils.py | 1 - griptape/utils/j2.py | 4 +- griptape/utils/python_runner.py | 1 + griptape/utils/stream.py | 12 ++++-- griptape/utils/structure_visualizer.py | 5 ++- pyproject.toml | 6 ++- 271 files changed, 1022 insertions(+), 555 deletions(-) diff --git a/griptape/artifacts/action_artifact.py b/griptape/artifacts/action_artifact.py index 210e24f9f..a10653078 100644 --- a/griptape/artifacts/action_artifact.py +++ b/griptape/artifacts/action_artifact.py @@ -1,8 +1,9 @@ from __future__ import annotations -from attrs import define, field from typing import TYPE_CHECKING +from attrs import define, field + from griptape.artifacts import BaseArtifact from griptape.mixins import SerializableMixin diff --git a/griptape/artifacts/base_artifact.py b/griptape/artifacts/base_artifact.py index 626e13f69..ef82110af 100644 --- a/griptape/artifacts/base_artifact.py +++ b/griptape/artifacts/base_artifact.py @@ -1,10 +1,13 @@ from __future__ import annotations -from griptape.mixins import SerializableMixin -from typing import Any, TYPE_CHECKING, Optional + import json import uuid from abc import ABC, abstractmethod -from attrs import define, field, Factory +from typing import TYPE_CHECKING, Any, Optional + +from attrs import Factory, define, field + +from griptape.mixins import SerializableMixin if TYPE_CHECKING: from griptape.common import Reference diff --git a/griptape/artifacts/blob_artifact.py b/griptape/artifacts/blob_artifact.py index 5d2f32272..0c0dcc122 100644 --- a/griptape/artifacts/blob_artifact.py +++ b/griptape/artifacts/blob_artifact.py @@ -1,7 +1,10 @@ from __future__ import annotations + import os.path from typing import Optional -from attrs import field, define + +from attrs import define, field + from griptape.artifacts import BaseArtifact diff --git a/griptape/artifacts/boolean_artifact.py b/griptape/artifacts/boolean_artifact.py index 0c5ae6f35..7719e9cfe 100644 --- a/griptape/artifacts/boolean_artifact.py +++ b/griptape/artifacts/boolean_artifact.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import Union + from attrs import define, field + from griptape.artifacts import BaseArtifact diff --git a/griptape/artifacts/csv_row_artifact.py b/griptape/artifacts/csv_row_artifact.py index 7572b7a2f..74b8f1a4e 100644 --- a/griptape/artifacts/csv_row_artifact.py +++ b/griptape/artifacts/csv_row_artifact.py @@ -1,8 +1,11 @@ from __future__ import annotations + import csv import io + from attrs import define, field -from griptape.artifacts import TextArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, TextArtifact @define diff --git a/griptape/artifacts/error_artifact.py b/griptape/artifacts/error_artifact.py index 1900002b3..d065d754b 100644 --- a/griptape/artifacts/error_artifact.py +++ b/griptape/artifacts/error_artifact.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import Optional + from attrs import define, field + from griptape.artifacts import BaseArtifact diff --git a/griptape/artifacts/info_artifact.py b/griptape/artifacts/info_artifact.py index 3692e9631..26fe6366b 100644 --- a/griptape/artifacts/info_artifact.py +++ b/griptape/artifacts/info_artifact.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define, field + from griptape.artifacts import BaseArtifact diff --git a/griptape/artifacts/list_artifact.py b/griptape/artifacts/list_artifact.py index 68b377df2..23cca6461 100644 --- a/griptape/artifacts/list_artifact.py +++ b/griptape/artifacts/list_artifact.py @@ -1,6 +1,8 @@ -from typing import Optional from collections.abc import Sequence -from attrs import field, define +from typing import Optional + +from attrs import define, field + from griptape.artifacts import BaseArtifact diff --git a/griptape/artifacts/media_artifact.py b/griptape/artifacts/media_artifact.py index 751f2bf62..a57217fc7 100644 --- a/griptape/artifacts/media_artifact.py +++ b/griptape/artifacts/media_artifact.py @@ -1,13 +1,14 @@ from __future__ import annotations +import base64 +import random import string import time -import random from typing import Optional from attrs import define, field + from griptape.artifacts import BlobArtifact -import base64 @define diff --git a/griptape/artifacts/text_artifact.py b/griptape/artifacts/text_artifact.py index e8a2bb2a7..1e44a8df5 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import TYPE_CHECKING, Optional + from attrs import define, field + from griptape.artifacts import BaseArtifact if TYPE_CHECKING: diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index 183264bb4..a6258d43b 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -1,7 +1,10 @@ from __future__ import annotations + from abc import ABC from typing import Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact from griptape.chunkers import ChunkSeparator from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer diff --git a/griptape/common/actions/base_action.py b/griptape/common/actions/base_action.py index 6bfda8f30..abd9abcd4 100644 --- a/griptape/common/actions/base_action.py +++ b/griptape/common/actions/base_action.py @@ -1,5 +1,6 @@ -from griptape.mixins import SerializableMixin from abc import ABC +from griptape.mixins import SerializableMixin + class BaseAction(SerializableMixin, ABC): ... diff --git a/griptape/common/actions/tool_action.py b/griptape/common/actions/tool_action.py index 2b03a10bb..1b84cd551 100644 --- a/griptape/common/actions/tool_action.py +++ b/griptape/common/actions/tool_action.py @@ -1,4 +1,5 @@ from __future__ import annotations + import json from typing import TYPE_CHECKING, Optional diff --git a/griptape/common/prompt_stack/contents/action_call_delta_message_content.py b/griptape/common/prompt_stack/contents/action_call_delta_message_content.py index 5e86aa164..4751cc13c 100644 --- a/griptape/common/prompt_stack/contents/action_call_delta_message_content.py +++ b/griptape/common/prompt_stack/contents/action_call_delta_message_content.py @@ -1,7 +1,9 @@ from __future__ import annotations -from attrs import define, field + from typing import Optional +from attrs import define, field + from griptape.common import BaseDeltaMessageContent diff --git a/griptape/common/prompt_stack/contents/action_call_message_content.py b/griptape/common/prompt_stack/contents/action_call_message_content.py index 55cc78324..e658af23d 100644 --- a/griptape/common/prompt_stack/contents/action_call_message_content.py +++ b/griptape/common/prompt_stack/contents/action_call_message_content.py @@ -1,13 +1,12 @@ from __future__ import annotations import json +from typing import TYPE_CHECKING from attrs import define, field -from griptape.common import ToolAction from griptape.artifacts import ActionArtifact -from griptape.common import BaseDeltaMessageContent, BaseMessageContent, ActionCallDeltaMessageContent -from typing import TYPE_CHECKING +from griptape.common import ActionCallDeltaMessageContent, BaseDeltaMessageContent, BaseMessageContent, ToolAction if TYPE_CHECKING: from collections.abc import Sequence diff --git a/griptape/common/prompt_stack/contents/action_result_message_content.py b/griptape/common/prompt_stack/contents/action_result_message_content.py index 8f75daaac..9b55b81ff 100644 --- a/griptape/common/prompt_stack/contents/action_result_message_content.py +++ b/griptape/common/prompt_stack/contents/action_result_message_content.py @@ -1,15 +1,16 @@ from __future__ import annotations +from typing import TYPE_CHECKING from attrs import define, field from griptape.common import BaseDeltaMessageContent, BaseMessageContent, ToolAction -from typing import TYPE_CHECKING if TYPE_CHECKING: - from griptape.artifacts import BaseArtifact from collections.abc import Sequence + from griptape.artifacts import BaseArtifact + @define class ActionResultMessageContent(BaseMessageContent): diff --git a/griptape/common/prompt_stack/contents/base_message_content.py b/griptape/common/prompt_stack/contents/base_message_content.py index 5515ef745..a0b10fd05 100644 --- a/griptape/common/prompt_stack/contents/base_message_content.py +++ b/griptape/common/prompt_stack/contents/base_message_content.py @@ -2,14 +2,18 @@ from abc import ABC, abstractmethod from typing import TYPE_CHECKING + from attrs import define, field + from griptape.mixins import SerializableMixin if TYPE_CHECKING: - from .base_delta_message_content import BaseDeltaMessageContent from collections.abc import Sequence + from griptape.artifacts.base_artifact import BaseArtifact + from .base_delta_message_content import BaseDeltaMessageContent + @define class BaseMessageContent(ABC, SerializableMixin): diff --git a/griptape/common/prompt_stack/contents/image_message_content.py b/griptape/common/prompt_stack/contents/image_message_content.py index 335004c30..37906ec38 100644 --- a/griptape/common/prompt_stack/contents/image_message_content.py +++ b/griptape/common/prompt_stack/contents/image_message_content.py @@ -1,15 +1,16 @@ from __future__ import annotations +from typing import TYPE_CHECKING from attrs import define, field from griptape.common import BaseDeltaMessageContent, BaseMessageContent -from typing import TYPE_CHECKING if TYPE_CHECKING: - from griptape.artifacts import ImageArtifact from collections.abc import Sequence + from griptape.artifacts import ImageArtifact + @define class ImageMessageContent(BaseMessageContent): diff --git a/griptape/common/prompt_stack/contents/text_delta_message_content.py b/griptape/common/prompt_stack/contents/text_delta_message_content.py index ab5313df6..23448261c 100644 --- a/griptape/common/prompt_stack/contents/text_delta_message_content.py +++ b/griptape/common/prompt_stack/contents/text_delta_message_content.py @@ -1,4 +1,5 @@ from __future__ import annotations + from attrs import define, field from griptape.common import BaseDeltaMessageContent diff --git a/griptape/common/prompt_stack/contents/text_message_content.py b/griptape/common/prompt_stack/contents/text_message_content.py index b98402097..c862564f3 100644 --- a/griptape/common/prompt_stack/contents/text_message_content.py +++ b/griptape/common/prompt_stack/contents/text_message_content.py @@ -1,10 +1,11 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from attrs import define, field from griptape.artifacts import TextArtifact -from griptape.common import BaseMessageContent, BaseDeltaMessageContent, TextDeltaMessageContent -from typing import TYPE_CHECKING +from griptape.common import BaseDeltaMessageContent, BaseMessageContent, TextDeltaMessageContent if TYPE_CHECKING: from collections.abc import Sequence diff --git a/griptape/common/prompt_stack/messages/base_message.py b/griptape/common/prompt_stack/messages/base_message.py index 84de85d7d..15bcd9c73 100644 --- a/griptape/common/prompt_stack/messages/base_message.py +++ b/griptape/common/prompt_stack/messages/base_message.py @@ -1,14 +1,14 @@ from __future__ import annotations from abc import ABC -from typing import Optional, Union, TYPE_CHECKING -from attrs import Factory, define, field +from typing import TYPE_CHECKING, Optional, Union +from attrs import Factory, define, field from griptape.mixins import SerializableMixin if TYPE_CHECKING: - from griptape.common import BaseMessageContent, BaseDeltaMessageContent + from griptape.common import BaseDeltaMessageContent, BaseMessageContent @define diff --git a/griptape/common/prompt_stack/messages/delta_message.py b/griptape/common/prompt_stack/messages/delta_message.py index b535451db..20aedbbe3 100644 --- a/griptape/common/prompt_stack/messages/delta_message.py +++ b/griptape/common/prompt_stack/messages/delta_message.py @@ -1,10 +1,9 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from attrs import define, field - from .base_message import BaseMessage if TYPE_CHECKING: diff --git a/griptape/common/prompt_stack/messages/message.py b/griptape/common/prompt_stack/messages/message.py index 8bc6f63e2..aaba331d9 100644 --- a/griptape/common/prompt_stack/messages/message.py +++ b/griptape/common/prompt_stack/messages/message.py @@ -4,7 +4,7 @@ from attrs import define, field -from griptape.artifacts import TextArtifact, ListArtifact, BaseArtifact +from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact from griptape.common import BaseMessageContent, TextMessageContent from .base_message import BaseMessage diff --git a/griptape/common/reference.py b/griptape/common/reference.py index d92c203f9..40b709df9 100644 --- a/griptape/common/reference.py +++ b/griptape/common/reference.py @@ -1,6 +1,8 @@ import uuid from typing import Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.mixins import SerializableMixin diff --git a/griptape/config/amazon_bedrock_structure_config.py b/griptape/config/amazon_bedrock_structure_config.py index cdb685c76..c99b59026 100644 --- a/griptape/config/amazon_bedrock_structure_config.py +++ b/griptape/config/amazon_bedrock_structure_config.py @@ -1,9 +1,9 @@ from __future__ import annotations + from typing import TYPE_CHECKING + from attrs import Factory, define, field -from griptape.drivers import BasePromptDriver -from griptape.utils import import_optional_dependency from griptape.config import StructureConfig from griptape.drivers import ( AmazonBedrockImageGenerationDriver, @@ -12,11 +12,13 @@ AmazonBedrockTitanEmbeddingDriver, BaseEmbeddingDriver, BaseImageGenerationDriver, + BasePromptDriver, BaseVectorStoreDriver, BedrockClaudeImageQueryModelDriver, BedrockTitanImageGenerationModelDriver, LocalVectorStoreDriver, ) +from griptape.utils import import_optional_dependency if TYPE_CHECKING: import boto3 diff --git a/griptape/config/azure_openai_structure_config.py b/griptape/config/azure_openai_structure_config.py index 3aee53f32..8361c7894 100644 --- a/griptape/config/azure_openai_structure_config.py +++ b/griptape/config/azure_openai_structure_config.py @@ -1,18 +1,19 @@ from typing import Callable, Optional + from attrs import Factory, define, field from griptape.config import StructureConfig from griptape.drivers import ( - LocalVectorStoreDriver, AzureOpenAiChatPromptDriver, AzureOpenAiEmbeddingDriver, AzureOpenAiImageGenerationDriver, AzureOpenAiImageQueryDriver, - BasePromptDriver, BaseEmbeddingDriver, BaseImageGenerationDriver, BaseImageQueryDriver, + BasePromptDriver, BaseVectorStoreDriver, + LocalVectorStoreDriver, ) diff --git a/griptape/config/base_structure_config.py b/griptape/config/base_structure_config.py index 2ceaf024f..a75cb9e80 100644 --- a/griptape/config/base_structure_config.py +++ b/griptape/config/base_structure_config.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from attrs import define, field @@ -10,14 +10,14 @@ if TYPE_CHECKING: from griptape.drivers import ( + BaseAudioTranscriptionDriver, BaseConversationMemoryDriver, BaseEmbeddingDriver, BaseImageGenerationDriver, BaseImageQueryDriver, BasePromptDriver, - BaseVectorStoreDriver, BaseTextToSpeechDriver, - BaseAudioTranscriptionDriver, + BaseVectorStoreDriver, ) diff --git a/griptape/config/cohere_structure_config.py b/griptape/config/cohere_structure_config.py index 82f11b8f4..c4c9f7eef 100644 --- a/griptape/config/cohere_structure_config.py +++ b/griptape/config/cohere_structure_config.py @@ -4,9 +4,9 @@ from griptape.drivers import ( BaseEmbeddingDriver, BasePromptDriver, - CoherePromptDriver, - CohereEmbeddingDriver, BaseVectorStoreDriver, + CohereEmbeddingDriver, + CoherePromptDriver, LocalVectorStoreDriver, ) diff --git a/griptape/config/openai_structure_config.py b/griptape/config/openai_structure_config.py index 416306a98..cce828913 100644 --- a/griptape/config/openai_structure_config.py +++ b/griptape/config/openai_structure_config.py @@ -2,20 +2,20 @@ from griptape.config import StructureConfig from griptape.drivers import ( + BaseAudioTranscriptionDriver, BaseEmbeddingDriver, BaseImageGenerationDriver, BaseImageQueryDriver, BasePromptDriver, + BaseTextToSpeechDriver, BaseVectorStoreDriver, LocalVectorStoreDriver, + OpenAiAudioTranscriptionDriver, OpenAiChatPromptDriver, OpenAiEmbeddingDriver, OpenAiImageGenerationDriver, - BaseTextToSpeechDriver, - OpenAiTextToSpeechDriver, - BaseAudioTranscriptionDriver, - OpenAiAudioTranscriptionDriver, OpenAiImageQueryDriver, + OpenAiTextToSpeechDriver, ) diff --git a/griptape/config/structure_config.py b/griptape/config/structure_config.py index ae3ad1e99..fe7bc7342 100644 --- a/griptape/config/structure_config.py +++ b/griptape/config/structure_config.py @@ -1,24 +1,24 @@ -from attrs import Factory, define, field from typing import Optional -from griptape.config import BaseStructureConfig +from attrs import Factory, define, field +from griptape.config import BaseStructureConfig from griptape.drivers import ( + BaseAudioTranscriptionDriver, BaseConversationMemoryDriver, BaseEmbeddingDriver, BaseImageGenerationDriver, + BaseImageQueryDriver, BasePromptDriver, + BaseTextToSpeechDriver, BaseVectorStoreDriver, - DummyVectorStoreDriver, + DummyAudioTranscriptionDriver, DummyEmbeddingDriver, DummyImageGenerationDriver, - DummyPromptDriver, DummyImageQueryDriver, - BaseImageQueryDriver, - BaseTextToSpeechDriver, + DummyPromptDriver, DummyTextToSpeechDriver, - BaseAudioTranscriptionDriver, - DummyAudioTranscriptionDriver, + DummyVectorStoreDriver, ) diff --git a/griptape/drivers/audio_transcription/base_audio_transcription_driver.py b/griptape/drivers/audio_transcription/base_audio_transcription_driver.py index 2ccf752b7..5a0c96648 100644 --- a/griptape/drivers/audio_transcription/base_audio_transcription_driver.py +++ b/griptape/drivers/audio_transcription/base_audio_transcription_driver.py @@ -5,11 +5,11 @@ from attrs import define, field -from griptape.events import StartAudioTranscriptionEvent, FinishAudioTranscriptionEvent +from griptape.events import FinishAudioTranscriptionEvent, StartAudioTranscriptionEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: - from griptape.artifacts import TextArtifact, AudioArtifact + from griptape.artifacts import AudioArtifact, TextArtifact from griptape.structures import Structure diff --git a/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py b/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py index 1602604e4..ba3da3231 100644 --- a/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py +++ b/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py @@ -1,6 +1,7 @@ from typing import Optional from attrs import define, field + from griptape.artifacts import AudioArtifact, TextArtifact from griptape.drivers import BaseAudioTranscriptionDriver from griptape.exceptions import DummyException diff --git a/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py b/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py index 14b367521..c2098bb67 100644 --- a/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py +++ b/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py @@ -4,7 +4,7 @@ from typing import Optional import openai -from attrs import field, Factory, define +from attrs import Factory, define, field from griptape.artifacts import AudioArtifact, TextArtifact from griptape.drivers import BaseAudioTranscriptionDriver diff --git a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py index fe113c300..41fbf2a92 100644 --- a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py @@ -1,15 +1,19 @@ from __future__ import annotations + import json -from typing import Any, TYPE_CHECKING -from attrs import define, field, Factory +from typing import TYPE_CHECKING, Any + +from attrs import Factory, define, field + from griptape.drivers import BaseEmbeddingDriver from griptape.tokenizers.amazon_bedrock_tokenizer import AmazonBedrockTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: - from griptape.tokenizers.base_tokenizer import BaseTokenizer import boto3 + from griptape.tokenizers.base_tokenizer import BaseTokenizer + @define class AmazonBedrockCohereEmbeddingDriver(BaseEmbeddingDriver): diff --git a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py index 1de4d6cfe..2eb83b033 100644 --- a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py @@ -1,15 +1,19 @@ from __future__ import annotations + import json -from typing import Any, TYPE_CHECKING -from attrs import define, field, Factory +from typing import TYPE_CHECKING, Any + +from attrs import Factory, define, field + from griptape.drivers import BaseEmbeddingDriver from griptape.tokenizers.amazon_bedrock_tokenizer import AmazonBedrockTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: - from griptape.tokenizers.base_tokenizer import BaseTokenizer import boto3 + from griptape.tokenizers.base_tokenizer import BaseTokenizer + @define class AmazonBedrockTitanEmbeddingDriver(BaseEmbeddingDriver): diff --git a/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py b/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py index 2b764c2f4..413ad2fe2 100644 --- a/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py @@ -1,7 +1,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING + import json -from typing import Any, Optional +from typing import TYPE_CHECKING, Any, Optional from attrs import Factory, define, field diff --git a/griptape/drivers/embedding/azure_openai_embedding_driver.py b/griptape/drivers/embedding/azure_openai_embedding_driver.py index bf78ef1ae..420458e29 100644 --- a/griptape/drivers/embedding/azure_openai_embedding_driver.py +++ b/griptape/drivers/embedding/azure_openai_embedding_driver.py @@ -1,10 +1,12 @@ from __future__ import annotations from typing import Callable, Optional -from attrs import define, field, Factory + +import openai +from attrs import Factory, define, field + from griptape.drivers import OpenAiEmbeddingDriver from griptape.tokenizers import OpenAiTokenizer -import openai @define diff --git a/griptape/drivers/embedding/base_embedding_driver.py b/griptape/drivers/embedding/base_embedding_driver.py index dc9e2c9ae..8998f00e5 100644 --- a/griptape/drivers/embedding/base_embedding_driver.py +++ b/griptape/drivers/embedding/base_embedding_driver.py @@ -1,11 +1,13 @@ from __future__ import annotations -import numpy as np -from typing import Optional, TYPE_CHECKING + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING, Optional + +import numpy as np from attrs import define, field -from griptape.mixins import ExponentialBackoffMixin + from griptape.chunkers import BaseChunker, TextChunker -from griptape.mixins import SerializableMixin +from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: from griptape.artifacts import TextArtifact diff --git a/griptape/drivers/embedding/cohere_embedding_driver.py b/griptape/drivers/embedding/cohere_embedding_driver.py index 13f72aa16..365dc972e 100644 --- a/griptape/drivers/embedding/cohere_embedding_driver.py +++ b/griptape/drivers/embedding/cohere_embedding_driver.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import TYPE_CHECKING -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.drivers import BaseEmbeddingDriver from griptape.tokenizers import CohereTokenizer from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/embedding/dummy_embedding_driver.py b/griptape/drivers/embedding/dummy_embedding_driver.py index 3aa4f739e..dadd02897 100644 --- a/griptape/drivers/embedding/dummy_embedding_driver.py +++ b/griptape/drivers/embedding/dummy_embedding_driver.py @@ -1,4 +1,5 @@ from attrs import define, field + from griptape.drivers import BaseEmbeddingDriver from griptape.exceptions import DummyException diff --git a/griptape/drivers/embedding/google_embedding_driver.py b/griptape/drivers/embedding/google_embedding_driver.py index b8745345c..f57c75611 100644 --- a/griptape/drivers/embedding/google_embedding_driver.py +++ b/griptape/drivers/embedding/google_embedding_driver.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import Optional + from attrs import define, field + from griptape.drivers import BaseEmbeddingDriver from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/embedding/huggingface_hub_embedding_driver.py b/griptape/drivers/embedding/huggingface_hub_embedding_driver.py index 8b47e56e9..9a8fd5292 100644 --- a/griptape/drivers/embedding/huggingface_hub_embedding_driver.py +++ b/griptape/drivers/embedding/huggingface_hub_embedding_driver.py @@ -1,8 +1,11 @@ from __future__ import annotations + from typing import TYPE_CHECKING -from griptape.utils import import_optional_dependency -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.drivers import BaseEmbeddingDriver +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from huggingface_hub import InferenceClient diff --git a/griptape/drivers/embedding/ollama_embedding_driver.py b/griptape/drivers/embedding/ollama_embedding_driver.py index f3f68a049..c5c30d5af 100644 --- a/griptape/drivers/embedding/ollama_embedding_driver.py +++ b/griptape/drivers/embedding/ollama_embedding_driver.py @@ -1,8 +1,11 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING -from attrs import define, field, Factory -from griptape.utils import import_optional_dependency + +from typing import TYPE_CHECKING, Optional + +from attrs import Factory, define, field + from griptape.drivers import BaseEmbeddingDriver +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from ollama import Client diff --git a/griptape/drivers/embedding/openai_embedding_driver.py b/griptape/drivers/embedding/openai_embedding_driver.py index 46b9e77b5..73c737d6b 100644 --- a/griptape/drivers/embedding/openai_embedding_driver.py +++ b/griptape/drivers/embedding/openai_embedding_driver.py @@ -1,9 +1,12 @@ from __future__ import annotations + from typing import Optional -from attrs import define, field, Factory + +import openai +from attrs import Factory, define, field + from griptape.drivers import BaseEmbeddingDriver from griptape.tokenizers import OpenAiTokenizer -import openai @define diff --git a/griptape/drivers/embedding/voyageai_embedding_driver.py b/griptape/drivers/embedding/voyageai_embedding_driver.py index 76bcf71b8..b29dd5692 100644 --- a/griptape/drivers/embedding/voyageai_embedding_driver.py +++ b/griptape/drivers/embedding/voyageai_embedding_driver.py @@ -1,9 +1,12 @@ from __future__ import annotations -from typing import Optional, Any -from attrs import define, field, Factory -from griptape.utils import import_optional_dependency + +from typing import Any, Optional + +from attrs import Factory, define, field + from griptape.drivers import BaseEmbeddingDriver from griptape.tokenizers import VoyageAiTokenizer +from griptape.utils import import_optional_dependency @define diff --git a/griptape/drivers/event_listener/base_event_listener_driver.py b/griptape/drivers/event_listener/base_event_listener_driver.py index cc0f9d36c..710e6382f 100644 --- a/griptape/drivers/event_listener/base_event_listener_driver.py +++ b/griptape/drivers/event_listener/base_event_listener_driver.py @@ -1,8 +1,10 @@ from __future__ import annotations + from abc import ABC, abstractmethod from concurrent import futures from logging import Logger -from typing import Callable, TYPE_CHECKING +from typing import TYPE_CHECKING, Callable + from attrs import Factory, define, field if TYPE_CHECKING: diff --git a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py index c481d3081..0ecf17d9b 100644 --- a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py +++ b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py @@ -1,10 +1,10 @@ from __future__ import annotations import os -import requests - from urllib.parse import urljoin -from attrs import define, field, Factory + +import requests +from attrs import Factory, define, field from griptape.drivers.event_listener.base_event_listener_driver import BaseEventListenerDriver diff --git a/griptape/drivers/event_listener/pusher_event_listener_driver.py b/griptape/drivers/event_listener/pusher_event_listener_driver.py index d41b679d7..2e9de8d72 100644 --- a/griptape/drivers/event_listener/pusher_event_listener_driver.py +++ b/griptape/drivers/event_listener/pusher_event_listener_driver.py @@ -1,7 +1,9 @@ from __future__ import annotations from typing import TYPE_CHECKING -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.drivers import BaseEventListenerDriver from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/event_listener/webhook_event_listener_driver.py b/griptape/drivers/event_listener/webhook_event_listener_driver.py index a0eb5ab5f..54fd532b6 100644 --- a/griptape/drivers/event_listener/webhook_event_listener_driver.py +++ b/griptape/drivers/event_listener/webhook_event_listener_driver.py @@ -1,7 +1,6 @@ from __future__ import annotations import requests - from attrs import define, field from griptape.drivers.event_listener.base_event_listener_driver import BaseEventListenerDriver diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index 840ae60d7..d9eae9696 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -1,9 +1,13 @@ from __future__ import annotations + import os from pathlib import Path from typing import TYPE_CHECKING, Any -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.utils.import_utils import import_optional_dependency + from .base_file_manager_driver import BaseFileManagerDriver if TYPE_CHECKING: diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index 546642554..b69aa374d 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -1,8 +1,11 @@ from __future__ import annotations + from abc import ABC, abstractmethod + from attrs import Factory, define, field -from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact, InfoArtifact, ListArtifact + import griptape.loaders as loaders +from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact @define diff --git a/griptape/drivers/file_manager/local_file_manager_driver.py b/griptape/drivers/file_manager/local_file_manager_driver.py index befe2fdd2..3dea4612b 100644 --- a/griptape/drivers/file_manager/local_file_manager_driver.py +++ b/griptape/drivers/file_manager/local_file_manager_driver.py @@ -1,7 +1,10 @@ from __future__ import annotations + import os from pathlib import Path -from attrs import define, field, Factory + +from attrs import Factory, define, field + from .base_file_manager_driver import BaseFileManagerDriver diff --git a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py index b5a4b7e3b..a8f4c2d2e 100644 --- a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py +++ b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py @@ -3,7 +3,7 @@ import json from typing import TYPE_CHECKING, Any, Optional -from attrs import define, field, Factory +from attrs import Factory, define, field from griptape.artifacts import ImageArtifact from griptape.drivers import BaseMultiModelImageGenerationDriver diff --git a/griptape/drivers/image_generation/azure_openai_image_generation_driver.py b/griptape/drivers/image_generation/azure_openai_image_generation_driver.py index b631703d8..d7ec7681a 100644 --- a/griptape/drivers/image_generation/azure_openai_image_generation_driver.py +++ b/griptape/drivers/image_generation/azure_openai_image_generation_driver.py @@ -1,9 +1,10 @@ from __future__ import annotations -import openai -from attrs import field, Factory, define from typing import Callable, Optional +import openai +from attrs import Factory, define, field + from griptape.drivers import OpenAiImageGenerationDriver diff --git a/griptape/drivers/image_generation/base_image_generation_driver.py b/griptape/drivers/image_generation/base_image_generation_driver.py index 704595aec..ee132605c 100644 --- a/griptape/drivers/image_generation/base_image_generation_driver.py +++ b/griptape/drivers/image_generation/base_image_generation_driver.py @@ -5,7 +5,7 @@ from attrs import define, field -from griptape.events import StartImageGenerationEvent, FinishImageGenerationEvent +from griptape.events import FinishImageGenerationEvent, StartImageGenerationEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: diff --git a/griptape/drivers/image_generation/base_multi_model_image_generation_driver.py b/griptape/drivers/image_generation/base_multi_model_image_generation_driver.py index 12c2fbef5..b1966d36b 100644 --- a/griptape/drivers/image_generation/base_multi_model_image_generation_driver.py +++ b/griptape/drivers/image_generation/base_multi_model_image_generation_driver.py @@ -1,7 +1,8 @@ from __future__ import annotations + from abc import ABC -from attrs import field, define +from attrs import define, field from griptape.drivers import BaseImageGenerationDriver, BaseImageGenerationModelDriver diff --git a/griptape/drivers/image_generation/dummy_image_generation_driver.py b/griptape/drivers/image_generation/dummy_image_generation_driver.py index 0f6b622f7..ac1961821 100644 --- a/griptape/drivers/image_generation/dummy_image_generation_driver.py +++ b/griptape/drivers/image_generation/dummy_image_generation_driver.py @@ -1,5 +1,7 @@ from typing import Optional + from attrs import define, field + from griptape.artifacts import ImageArtifact from griptape.drivers import BaseImageGenerationDriver from griptape.exceptions import DummyException diff --git a/griptape/drivers/image_generation/leonardo_image_generation_driver.py b/griptape/drivers/image_generation/leonardo_image_generation_driver.py index d274970ee..44d583683 100644 --- a/griptape/drivers/image_generation/leonardo_image_generation_driver.py +++ b/griptape/drivers/image_generation/leonardo_image_generation_driver.py @@ -1,9 +1,9 @@ import json import time -from typing import Optional, Literal +from typing import Literal, Optional import requests -from attrs import field, define, Factory +from attrs import Factory, define, field from griptape.artifacts import ImageArtifact from griptape.drivers import BaseImageGenerationDriver diff --git a/griptape/drivers/image_generation/openai_image_generation_driver.py b/griptape/drivers/image_generation/openai_image_generation_driver.py index 72ce20a92..d3e8ce727 100644 --- a/griptape/drivers/image_generation/openai_image_generation_driver.py +++ b/griptape/drivers/image_generation/openai_image_generation_driver.py @@ -1,10 +1,10 @@ from __future__ import annotations import base64 -from typing import Literal, Optional, cast, Union, TYPE_CHECKING +from typing import TYPE_CHECKING, Literal, Optional, Union, cast import openai -from attrs import field, Factory, define +from attrs import Factory, define, field from griptape.artifacts import ImageArtifact from griptape.drivers import BaseImageGenerationDriver diff --git a/griptape/drivers/image_generation_model/base_image_generation_model_driver.py b/griptape/drivers/image_generation_model/base_image_generation_model_driver.py index c5cc6ff2d..9acc62890 100644 --- a/griptape/drivers/image_generation_model/base_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/base_image_generation_model_driver.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Any, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, Optional from attrs import define diff --git a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py index c0206dea0..78bcecc87 100644 --- a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py @@ -2,9 +2,9 @@ import base64 import logging -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional -from attrs import field, define +from attrs import define, field from griptape.drivers import BaseImageGenerationModelDriver diff --git a/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py b/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py index bfa998c1d..77a866c45 100644 --- a/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/bedrock_titan_image_generation_model_driver.py @@ -1,9 +1,9 @@ from __future__ import annotations import base64 -from typing import Any, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, Optional -from attrs import field, define +from attrs import define, field from griptape.drivers import BaseImageGenerationModelDriver diff --git a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py index 1377bfce9..cc1d13f4e 100644 --- a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py +++ b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py @@ -1,14 +1,18 @@ from __future__ import annotations + +import json from typing import TYPE_CHECKING, Any -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.drivers import BaseMultiModelImageQueryDriver from griptape.utils import import_optional_dependency -import json if TYPE_CHECKING: - from griptape.artifacts import ImageArtifact, TextArtifact import boto3 + from griptape.artifacts import ImageArtifact, TextArtifact + @define class AmazonBedrockImageQueryDriver(BaseMultiModelImageQueryDriver): diff --git a/griptape/drivers/image_query/anthropic_image_query_driver.py b/griptape/drivers/image_query/anthropic_image_query_driver.py index 9bc9ec4ae..fe39177ab 100644 --- a/griptape/drivers/image_query/anthropic_image_query_driver.py +++ b/griptape/drivers/image_query/anthropic_image_query_driver.py @@ -1,6 +1,9 @@ from __future__ import annotations -from typing import Optional, Any -from attrs import define, field, Factory + +from typing import Any, Optional + +from attrs import Factory, define, field + from griptape.artifacts import ImageArtifact, TextArtifact from griptape.drivers import BaseImageQueryDriver from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/image_query/azure_openai_image_query_driver.py b/griptape/drivers/image_query/azure_openai_image_query_driver.py index f59c64823..ad37737c7 100644 --- a/griptape/drivers/image_query/azure_openai_image_query_driver.py +++ b/griptape/drivers/image_query/azure_openai_image_query_driver.py @@ -2,8 +2,9 @@ from typing import Callable, Optional -from attrs import define, field, Factory import openai +from attrs import Factory, define, field + from griptape.drivers.image_query.openai_image_query_driver import OpenAiImageQueryDriver diff --git a/griptape/drivers/image_query/base_image_query_driver.py b/griptape/drivers/image_query/base_image_query_driver.py index 44aa13ce2..3f606e749 100644 --- a/griptape/drivers/image_query/base_image_query_driver.py +++ b/griptape/drivers/image_query/base_image_query_driver.py @@ -1,15 +1,15 @@ from __future__ import annotations -from abc import abstractmethod, ABC -from typing import Optional, TYPE_CHECKING +from abc import ABC, abstractmethod +from typing import TYPE_CHECKING, Optional from attrs import define, field -from griptape.events import StartImageQueryEvent, FinishImageQueryEvent +from griptape.events import FinishImageQueryEvent, StartImageQueryEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: - from griptape.artifacts import TextArtifact, ImageArtifact + from griptape.artifacts import ImageArtifact, TextArtifact from griptape.structures import Structure diff --git a/griptape/drivers/image_query/base_multi_model_image_query_driver.py b/griptape/drivers/image_query/base_multi_model_image_query_driver.py index d801fd917..52af617e8 100644 --- a/griptape/drivers/image_query/base_multi_model_image_query_driver.py +++ b/griptape/drivers/image_query/base_multi_model_image_query_driver.py @@ -1,7 +1,8 @@ from __future__ import annotations + from abc import ABC -from attrs import field, define +from attrs import define, field from griptape.drivers import BaseImageQueryDriver, BaseImageQueryModelDriver diff --git a/griptape/drivers/image_query/dummy_image_query_driver.py b/griptape/drivers/image_query/dummy_image_query_driver.py index ddc6e2318..43d481c68 100644 --- a/griptape/drivers/image_query/dummy_image_query_driver.py +++ b/griptape/drivers/image_query/dummy_image_query_driver.py @@ -1,6 +1,6 @@ from attrs import define, field -from griptape.artifacts import TextArtifact, ImageArtifact +from griptape.artifacts import ImageArtifact, TextArtifact from griptape.drivers import BaseImageQueryDriver from griptape.exceptions import DummyException diff --git a/griptape/drivers/image_query/openai_image_query_driver.py b/griptape/drivers/image_query/openai_image_query_driver.py index 8b0020c2c..693f67184 100644 --- a/griptape/drivers/image_query/openai_image_query_driver.py +++ b/griptape/drivers/image_query/openai_image_query_driver.py @@ -2,14 +2,14 @@ from typing import Literal, Optional -from attrs import define, field, Factory +import openai +from attrs import Factory, define, field from openai.types.chat import ( - ChatCompletionUserMessageParam, + ChatCompletionContentPartImageParam, ChatCompletionContentPartParam, ChatCompletionContentPartTextParam, - ChatCompletionContentPartImageParam, + ChatCompletionUserMessageParam, ) -import openai from griptape.artifacts import ImageArtifact, TextArtifact from griptape.drivers.image_query.base_image_query_driver import BaseImageQueryDriver diff --git a/griptape/drivers/image_query_model/base_image_query_model_driver.py b/griptape/drivers/image_query_model/base_image_query_model_driver.py index 39d858288..5f60367d5 100644 --- a/griptape/drivers/image_query_model/base_image_query_model_driver.py +++ b/griptape/drivers/image_query_model/base_image_query_model_driver.py @@ -1,11 +1,14 @@ from __future__ import annotations + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING + from attrs import define + from griptape.mixins import SerializableMixin -from typing import TYPE_CHECKING if TYPE_CHECKING: - from griptape.artifacts import TextArtifact, ImageArtifact + from griptape.artifacts import ImageArtifact, TextArtifact @define diff --git a/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py b/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py index 3d3ca0164..ccb902a81 100644 --- a/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py +++ b/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define + from griptape.artifacts import ImageArtifact, TextArtifact from griptape.drivers import BaseImageQueryModelDriver diff --git a/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py b/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py index 36f62c0e5..e52174c28 100644 --- a/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/amazon_dynamodb_conversation_memory_driver.py @@ -1,9 +1,12 @@ from __future__ import annotations -from attrs import define, field, Factory -from typing import Optional, TYPE_CHECKING, Any -from griptape.utils import import_optional_dependency + +from typing import TYPE_CHECKING, Any, Optional + +from attrs import Factory, define, field + from griptape.drivers import BaseConversationMemoryDriver from griptape.memory.structure import BaseConversationMemory +from griptape.utils import import_optional_dependency if TYPE_CHECKING: import boto3 diff --git a/griptape/drivers/memory/conversation/base_conversation_memory_driver.py b/griptape/drivers/memory/conversation/base_conversation_memory_driver.py index 28299a7e4..1caeb902f 100644 --- a/griptape/drivers/memory/conversation/base_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/base_conversation_memory_driver.py @@ -1,6 +1,8 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING, Optional + from griptape.mixins import SerializableMixin if TYPE_CHECKING: diff --git a/griptape/drivers/memory/conversation/local_conversation_memory_driver.py b/griptape/drivers/memory/conversation/local_conversation_memory_driver.py index 9e3f4ffc9..b94bd3065 100644 --- a/griptape/drivers/memory/conversation/local_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/local_conversation_memory_driver.py @@ -1,6 +1,8 @@ import os -from attrs import define, field from typing import Optional + +from attrs import define, field + from griptape.drivers import BaseConversationMemoryDriver from griptape.memory.structure import BaseConversationMemory diff --git a/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py b/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py index 3de8737b8..531b009af 100644 --- a/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py @@ -1,7 +1,10 @@ from __future__ import annotations + import uuid -from attrs import define, field, Factory -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional + +from attrs import Factory, define, field + from griptape.drivers import BaseConversationMemoryDriver from griptape.memory.structure import BaseConversationMemory from griptape.utils.import_utils import import_optional_dependency diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 0b56af445..824e3abcc 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -33,6 +33,7 @@ if TYPE_CHECKING: from collections.abc import Iterator + import boto3 from griptape.common import PromptStack diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 08ec3a3fa..9eafed64a 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -6,13 +6,14 @@ from attrs import Factory, define, field from griptape.artifacts import TextArtifact -from griptape.common import PromptStack, Message, TextMessageContent, DeltaMessage +from griptape.common import DeltaMessage, Message, PromptStack, TextMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: from collections.abc import Iterator + import boto3 from griptape.common import PromptStack diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index d42fee46f..9eed9c275 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -15,18 +15,18 @@ TextArtifact, ) from griptape.common import ( + ActionCallDeltaMessageContent, ActionCallMessageContent, ActionResultMessageContent, BaseDeltaMessageContent, BaseMessageContent, - ActionCallDeltaMessageContent, DeltaMessage, - TextDeltaMessageContent, ImageMessageContent, - PromptStack, Message, - ToolAction, + PromptStack, + TextDeltaMessageContent, TextMessageContent, + ToolAction, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AnthropicTokenizer, BaseTokenizer @@ -34,6 +34,7 @@ if TYPE_CHECKING: from collections.abc import Iterator + from anthropic import Client from anthropic.types import ContentBlock, ContentBlockDeltaEvent, ContentBlockStartEvent diff --git a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py index 0b33aa103..0f8c76ea9 100644 --- a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py @@ -1,8 +1,10 @@ -from attrs import define, field, Factory from typing import Callable, Optional + +import openai +from attrs import Factory, define, field + from griptape.common import PromptStack from griptape.drivers import OpenAiChatPromptDriver -import openai @define diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 7a5c0cfc1..3f957c34e 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -6,22 +6,23 @@ from attrs import Factory, define, field from griptape.common import ( + ActionCallDeltaMessageContent, ActionCallMessageContent, BaseDeltaMessageContent, - ActionCallDeltaMessageContent, DeltaMessage, - TextDeltaMessageContent, - PromptStack, Message, + PromptStack, + TextDeltaMessageContent, TextMessageContent, ) from griptape.events import CompletionChunkEvent, FinishPromptEvent, StartPromptEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin if TYPE_CHECKING: - from griptape.tokenizers import BaseTokenizer from collections.abc import Iterator + from griptape.structures import Structure + from griptape.tokenizers import BaseTokenizer @define(kw_only=True) diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index 3943e2211..d44016d19 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -1,31 +1,34 @@ from __future__ import annotations + from typing import TYPE_CHECKING, Any -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact + +from attrs import Factory, define, field + +from griptape.artifacts import ActionArtifact, TextArtifact from griptape.artifacts.list_artifact import ListArtifact -from griptape.common.prompt_stack.contents.action_call_delta_message_content import ActionCallDeltaMessageContent -from griptape.drivers import BasePromptDriver -from griptape.tokenizers import CohereTokenizer -from griptape.artifacts import ActionArtifact from griptape.common import ( ActionCallMessageContent, + ActionResultMessageContent, BaseDeltaMessageContent, BaseMessageContent, DeltaMessage, - TextDeltaMessageContent, - PromptStack, Message, + PromptStack, + TextDeltaMessageContent, TextMessageContent, - ActionResultMessageContent, ToolAction, ) +from griptape.common.prompt_stack.contents.action_call_delta_message_content import ActionCallDeltaMessageContent +from griptape.drivers import BasePromptDriver +from griptape.tokenizers import BaseTokenizer, CohereTokenizer from griptape.utils import import_optional_dependency -from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: from collections.abc import Iterator + from cohere import Client from cohere.types import NonStreamedChatResponse + from griptape.tools import BaseTool diff --git a/griptape/drivers/prompt/dummy_prompt_driver.py b/griptape/drivers/prompt/dummy_prompt_driver.py index 301474954..c26d53794 100644 --- a/griptape/drivers/prompt/dummy_prompt_driver.py +++ b/griptape/drivers/prompt/dummy_prompt_driver.py @@ -1,16 +1,18 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from attrs import Factory, define, field from griptape.drivers import BasePromptDriver from griptape.exceptions import DummyException from griptape.tokenizers import DummyTokenizer -from typing import TYPE_CHECKING if TYPE_CHECKING: - from griptape.common import PromptStack, Message, DeltaMessage from collections.abc import Iterator + from griptape.common import DeltaMessage, Message, PromptStack + @define class DummyPromptDriver(BasePromptDriver): diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 02b9f0f87..ed85f6229 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -4,34 +4,34 @@ from typing import TYPE_CHECKING, Optional from attrs import Factory, define, field +from schema import Schema - +from griptape.artifacts import ActionArtifact, TextArtifact from griptape.common import ( + ActionCallDeltaMessageContent, + ActionCallMessageContent, + ActionResultMessageContent, + BaseDeltaMessageContent, BaseMessageContent, DeltaMessage, - TextDeltaMessageContent, ImageMessageContent, - PromptStack, Message, + PromptStack, + TextDeltaMessageContent, TextMessageContent, - ActionCallMessageContent, - ActionResultMessageContent, - ActionCallDeltaMessageContent, - BaseDeltaMessageContent, ToolAction, ) -from griptape.artifacts import TextArtifact, ActionArtifact from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer, GoogleTokenizer from griptape.utils import import_optional_dependency, remove_key_in_dict_recursively -from schema import Schema if TYPE_CHECKING: - from google.generativeai.types import ContentsType from collections.abc import Iterator + from google.generativeai import GenerativeModel - from google.generativeai.types import ContentDict, GenerateContentResponse from google.generativeai.protos import Part + from google.generativeai.types import ContentDict, ContentsType, GenerateContentResponse + from griptape.tools import BaseTool diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index 1c5647856..7d1debbf7 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -4,13 +4,14 @@ from attrs import Factory, define, field +from griptape.common import DeltaMessage, Message, PromptStack, TextDeltaMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer -from griptape.common import PromptStack, Message, DeltaMessage, TextDeltaMessageContent from griptape.utils import import_optional_dependency if TYPE_CHECKING: from collections.abc import Iterator + from huggingface_hub import InferenceClient diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index 9273deb0c..caff742c3 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -5,13 +5,14 @@ from attrs import Factory, define, field from griptape.artifacts import TextArtifact -from griptape.common import DeltaMessage, PromptStack, Message, TextMessageContent +from griptape.common import DeltaMessage, Message, PromptStack, TextMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import import_optional_dependency if TYPE_CHECKING: from collections.abc import Iterator + from transformers import TextGenerationPipeline diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py index 0818bd5e8..040099070 100644 --- a/griptape/drivers/prompt/ollama_prompt_driver.py +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -1,19 +1,28 @@ from __future__ import annotations + from collections.abc import Iterator from typing import TYPE_CHECKING, Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact +from griptape.common import ( + DeltaMessage, + ImageMessageContent, + Message, + PromptStack, + TextDeltaMessageContent, + TextMessageContent, +) from griptape.drivers import BasePromptDriver -from griptape.common import PromptStack, TextMessageContent -from griptape.utils import import_optional_dependency from griptape.tokenizers import SimpleTokenizer -from griptape.common import Message, DeltaMessage, TextDeltaMessageContent -from griptape.common import ImageMessageContent +from griptape.utils import import_optional_dependency if TYPE_CHECKING: - from griptape.tokenizers.base_tokenizer import BaseTokenizer from ollama import Client + from griptape.tokenizers.base_tokenizer import BaseTokenizer + @define class OllamaPromptDriver(BasePromptDriver): diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index b706cbeb6..f5b3796ed 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -7,18 +7,18 @@ from attrs import Factory, define, field from schema import Schema -from griptape.artifacts import TextArtifact, ActionArtifact +from griptape.artifacts import ActionArtifact, TextArtifact from griptape.common import ( + ActionCallDeltaMessageContent, ActionCallMessageContent, ActionResultMessageContent, BaseDeltaMessageContent, BaseMessageContent, - ActionCallDeltaMessageContent, DeltaMessage, - TextDeltaMessageContent, ImageMessageContent, - PromptStack, Message, + PromptStack, + TextDeltaMessageContent, TextMessageContent, ToolAction, ) @@ -27,6 +27,7 @@ if TYPE_CHECKING: from collections.abc import Iterator + from openai.types.chat.chat_completion_chunk import ChoiceDelta from openai.types.chat.chat_completion_message import ChatCompletionMessage diff --git a/griptape/drivers/rerank/base_rerank_driver.py b/griptape/drivers/rerank/base_rerank_driver.py index 975575d49..8193a108d 100644 --- a/griptape/drivers/rerank/base_rerank_driver.py +++ b/griptape/drivers/rerank/base_rerank_driver.py @@ -1,5 +1,7 @@ from abc import ABC, abstractmethod + from attrs import define + from griptape.artifacts import TextArtifact diff --git a/griptape/drivers/rerank/cohere_rerank_driver.py b/griptape/drivers/rerank/cohere_rerank_driver.py index 6475ba766..36956452c 100644 --- a/griptape/drivers/rerank/cohere_rerank_driver.py +++ b/griptape/drivers/rerank/cohere_rerank_driver.py @@ -1,13 +1,17 @@ from __future__ import annotations + from typing import TYPE_CHECKING, Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.drivers import BaseRerankDriver from griptape.utils import import_optional_dependency if TYPE_CHECKING: - from griptape.artifacts import TextArtifact from cohere import Client + from griptape.artifacts import TextArtifact + @define(kw_only=True) class CohereRerankDriver(BaseRerankDriver): diff --git a/griptape/drivers/sql/amazon_redshift_sql_driver.py b/griptape/drivers/sql/amazon_redshift_sql_driver.py index e6ec8b2b9..edb7d39cb 100644 --- a/griptape/drivers/sql/amazon_redshift_sql_driver.py +++ b/griptape/drivers/sql/amazon_redshift_sql_driver.py @@ -1,9 +1,12 @@ from __future__ import annotations + import time -from typing import Optional, TYPE_CHECKING, Any -from griptape.drivers import BaseSqlDriver +from typing import TYPE_CHECKING, Any, Optional + from attrs import Factory, define, field +from griptape.drivers import BaseSqlDriver + if TYPE_CHECKING: import boto3 diff --git a/griptape/drivers/sql/base_sql_driver.py b/griptape/drivers/sql/base_sql_driver.py index 564746389..db05615b9 100644 --- a/griptape/drivers/sql/base_sql_driver.py +++ b/griptape/drivers/sql/base_sql_driver.py @@ -1,6 +1,7 @@ from abc import ABC, abstractmethod from dataclasses import dataclass -from typing import Optional, Any +from typing import Any, Optional + from attrs import define diff --git a/griptape/drivers/sql/snowflake_sql_driver.py b/griptape/drivers/sql/snowflake_sql_driver.py index 4c85ab3a3..2b89ec720 100644 --- a/griptape/drivers/sql/snowflake_sql_driver.py +++ b/griptape/drivers/sql/snowflake_sql_driver.py @@ -1,12 +1,15 @@ from __future__ import annotations -from typing import Callable, Optional, TYPE_CHECKING, Any -from griptape.utils import import_optional_dependency -from griptape.drivers import BaseSqlDriver + +from typing import TYPE_CHECKING, Any, Callable, Optional + from attrs import Factory, define, field +from griptape.drivers import BaseSqlDriver +from griptape.utils import import_optional_dependency + if TYPE_CHECKING: - from sqlalchemy.engine import Engine from snowflake.connector import SnowflakeConnection + from sqlalchemy.engine import Engine @define diff --git a/griptape/drivers/sql/sql_driver.py b/griptape/drivers/sql/sql_driver.py index a789a90c3..d3da01e2e 100644 --- a/griptape/drivers/sql/sql_driver.py +++ b/griptape/drivers/sql/sql_driver.py @@ -1,8 +1,11 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING, Any + +from typing import TYPE_CHECKING, Any, Optional + +from attrs import define, field + from griptape.drivers import BaseSqlDriver from griptape.utils import import_optional_dependency -from attrs import define, field if TYPE_CHECKING: from sqlalchemy.engine import Engine diff --git a/griptape/drivers/structure_run/base_structure_run_driver.py b/griptape/drivers/structure_run/base_structure_run_driver.py index 4ff9b6eb2..5bf2c9a5f 100644 --- a/griptape/drivers/structure_run/base_structure_run_driver.py +++ b/griptape/drivers/structure_run/base_structure_run_driver.py @@ -1,6 +1,6 @@ from abc import ABC, abstractmethod -from attrs import define, Factory, field +from attrs import Factory, define, field from griptape.artifacts import BaseArtifact diff --git a/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py b/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py index 40e6ff874..f2cda50be 100644 --- a/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py +++ b/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py @@ -69,7 +69,7 @@ def _get_structure_run_result(self, structure_run_id: str) -> InfoArtifact | Tex return InfoArtifact("No output found in response") def _get_structure_run_result_attempt(self, structure_run_url: str) -> Any: - from requests import get, Response + from requests import Response, get response: Response = get(structure_run_url, headers=self.headers) response.raise_for_status() diff --git a/griptape/drivers/structure_run/local_structure_run_driver.py b/griptape/drivers/structure_run/local_structure_run_driver.py index 4f140c1fe..c0049b29a 100644 --- a/griptape/drivers/structure_run/local_structure_run_driver.py +++ b/griptape/drivers/structure_run/local_structure_run_driver.py @@ -1,4 +1,6 @@ from __future__ import annotations + +import os from typing import TYPE_CHECKING, Callable from attrs import define, field @@ -6,8 +8,6 @@ from griptape.artifacts import BaseArtifact, InfoArtifact from griptape.drivers.structure_run.base_structure_run_driver import BaseStructureRunDriver -import os - if TYPE_CHECKING: from griptape.structures import Structure diff --git a/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py b/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py index b34b06019..bfef900c5 100644 --- a/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py @@ -1,4 +1,5 @@ from attrs import define, field + from griptape.artifacts.audio_artifact import AudioArtifact from griptape.drivers import BaseTextToSpeechDriver from griptape.exceptions import DummyException diff --git a/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py b/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py index 02d55c023..96d0ded0c 100644 --- a/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py @@ -2,7 +2,7 @@ from typing import Any -from attrs import define, field, Factory +from attrs import Factory, define, field from griptape.artifacts.audio_artifact import AudioArtifact from griptape.drivers import BaseTextToSpeechDriver diff --git a/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py b/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py index 2d6e7b155..8d8a81ad2 100644 --- a/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py @@ -1,9 +1,9 @@ from __future__ import annotations -from typing import Optional, Literal +from typing import Literal, Optional import openai -from attrs import define, field, Factory +from attrs import Factory, define, field from griptape.artifacts.audio_artifact import AudioArtifact from griptape.drivers import BaseTextToSpeechDriver diff --git a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py index d53ac2c64..140e429f1 100644 --- a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py @@ -1,6 +1,9 @@ from __future__ import annotations -from attrs import define, field, Factory -from typing import Optional, TYPE_CHECKING + +from typing import TYPE_CHECKING, Optional + +from attrs import Factory, define, field + from griptape.drivers import OpenSearchVectorStoreDriver from griptape.utils import import_optional_dependency, str_to_hash diff --git a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py index e29a7fa70..a1043040b 100644 --- a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py +++ b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import Optional + from attrs import define + from griptape.drivers import BaseVectorStoreDriver, MongoDbAtlasVectorStoreDriver diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 98c078fd6..9f9a13ea2 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -1,13 +1,15 @@ from __future__ import annotations + import uuid from abc import ABC, abstractmethod from concurrent import futures from dataclasses import dataclass -from typing import Any, Callable -from typing import Optional, TYPE_CHECKING -from attrs import define, field, Factory +from typing import TYPE_CHECKING, Any, Callable, Optional + +from attrs import Factory, define, field + from griptape import utils -from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact +from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact from griptape.mixins import SerializableMixin if TYPE_CHECKING: diff --git a/griptape/drivers/vector/dummy_vector_store_driver.py b/griptape/drivers/vector/dummy_vector_store_driver.py index 04dea2181..d1a6fdf0e 100644 --- a/griptape/drivers/vector/dummy_vector_store_driver.py +++ b/griptape/drivers/vector/dummy_vector_store_driver.py @@ -1,6 +1,8 @@ -from attrs import field, define, Factory from typing import Optional -from griptape.drivers import BaseVectorStoreDriver, BaseEmbeddingDriver, DummyEmbeddingDriver + +from attrs import Factory, define, field + +from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver from griptape.exceptions import DummyException diff --git a/griptape/drivers/vector/local_vector_store_driver.py b/griptape/drivers/vector/local_vector_store_driver.py index 1a86225c6..2ed76056e 100644 --- a/griptape/drivers/vector/local_vector_store_driver.py +++ b/griptape/drivers/vector/local_vector_store_driver.py @@ -2,10 +2,12 @@ import os import threading from dataclasses import asdict -from typing import Optional, Callable, TextIO -from attrs import define, field, Factory +from typing import Callable, Optional, TextIO + +from attrs import Factory, define, field from numpy import dot from numpy.linalg import norm + from griptape import utils from griptape.drivers import BaseVectorStoreDriver diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index 2e4d0acf0..08c7b89bb 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -1,14 +1,18 @@ from __future__ import annotations -from typing import Optional, Any, TYPE_CHECKING + +from typing import TYPE_CHECKING, Any, Optional + +from attrs import Factory, define, field + from griptape import utils -from griptape.utils import import_optional_dependency from griptape.drivers import BaseVectorStoreDriver -from attrs import define, field, Factory +from griptape.utils import import_optional_dependency if TYPE_CHECKING: - from griptape.artifacts import TextArtifact import marqo + from griptape.artifacts import TextArtifact + @define class MarqoVectorStoreDriver(BaseVectorStoreDriver): diff --git a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py index e60524714..e27f48b79 100644 --- a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py +++ b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import TYPE_CHECKING, Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.drivers import BaseVectorStoreDriver from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/vector/opensearch_vector_store_driver.py b/griptape/drivers/vector/opensearch_vector_store_driver.py index 49e73af96..3819cf791 100644 --- a/griptape/drivers/vector/opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/opensearch_vector_store_driver.py @@ -1,10 +1,13 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING -from griptape import utils + import logging -from griptape.utils import import_optional_dependency +from typing import TYPE_CHECKING, Optional + +from attrs import Factory, define, field + +from griptape import utils from griptape.drivers import BaseVectorStoreDriver -from attrs import define, field, Factory +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from opensearchpy import OpenSearch diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index abe01098a..3b3e5646f 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -1,15 +1,17 @@ import uuid -from typing import Optional, Any, cast -from attrs import define, field, Factory +from collections import OrderedDict from dataclasses import dataclass -from griptape.drivers import BaseVectorStoreDriver -from griptape.utils import import_optional_dependency +from typing import Any, Optional, cast + +from attrs import Factory, define, field +from sqlalchemy import JSON, Column, String, create_engine +from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.engine import Engine -from sqlalchemy import create_engine, Column, String, JSON from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Session -from collections import OrderedDict + +from griptape.drivers import BaseVectorStoreDriver +from griptape.utils import import_optional_dependency @define diff --git a/griptape/drivers/vector/pinecone_vector_store_driver.py b/griptape/drivers/vector/pinecone_vector_store_driver.py index 6da2f2418..634a707e7 100644 --- a/griptape/drivers/vector/pinecone_vector_store_driver.py +++ b/griptape/drivers/vector/pinecone_vector_store_driver.py @@ -1,9 +1,12 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING, Any -from griptape.utils import str_to_hash, import_optional_dependency -from griptape.drivers import BaseVectorStoreDriver + +from typing import TYPE_CHECKING, Any, Optional + from attrs import define, field +from griptape.drivers import BaseVectorStoreDriver +from griptape.utils import import_optional_dependency, str_to_hash + if TYPE_CHECKING: import pinecone diff --git a/griptape/drivers/vector/qdrant_vector_store_driver.py b/griptape/drivers/vector/qdrant_vector_store_driver.py index 0b96f03b9..34345b6df 100644 --- a/griptape/drivers/vector/qdrant_vector_store_driver.py +++ b/griptape/drivers/vector/qdrant_vector_store_driver.py @@ -1,10 +1,13 @@ from __future__ import annotations + +import logging +import uuid from typing import Optional + from attrs import define, field + from griptape.drivers import BaseVectorStoreDriver from griptape.utils import import_optional_dependency -import uuid -import logging DEFAULT_DISTANCE = "Cosine" CONTENT_PAYLOAD_KEY = "data" diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index e58e4b3ea..35a171cee 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -1,10 +1,13 @@ from __future__ import annotations + import json +from typing import TYPE_CHECKING, Optional + import numpy as np -from griptape.utils import import_optional_dependency, str_to_hash -from typing import Optional, TYPE_CHECKING -from attrs import define, field, Factory +from attrs import Factory, define, field + from griptape.drivers import BaseVectorStoreDriver +from griptape.utils import import_optional_dependency, str_to_hash if TYPE_CHECKING: from redis import Redis diff --git a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py index 28f225ba8..3945c786a 100644 --- a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py @@ -1,6 +1,8 @@ import re from typing import Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact from griptape.drivers import BaseWebScraperDriver from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/web_scraper/proxy_web_scraper_driver.py b/griptape/drivers/web_scraper/proxy_web_scraper_driver.py index 4a9213365..2d785fde2 100644 --- a/griptape/drivers/web_scraper/proxy_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/proxy_web_scraper_driver.py @@ -1,7 +1,7 @@ from __future__ import annotations -from attrs import field, Factory, define import requests +from attrs import Factory, define, field from griptape.artifacts import TextArtifact from griptape.drivers import BaseWebScraperDriver diff --git a/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py b/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py index cc0ca3a18..f0adfae22 100644 --- a/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py @@ -1,6 +1,8 @@ import json import logging + from attrs import define, field + from griptape.artifacts import TextArtifact from griptape.drivers import BaseWebScraperDriver from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/web_search/base_web_search_driver.py b/griptape/drivers/web_search/base_web_search_driver.py index 2b5662155..b561085ef 100644 --- a/griptape/drivers/web_search/base_web_search_driver.py +++ b/griptape/drivers/web_search/base_web_search_driver.py @@ -1,5 +1,6 @@ from abc import ABC, abstractmethod -from attrs import field, define + +from attrs import define, field from griptape.artifacts import ListArtifact diff --git a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py index ade6ed85c..7e5c8b287 100644 --- a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py +++ b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py @@ -1,8 +1,11 @@ from __future__ import annotations + import json from typing import TYPE_CHECKING -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact, ListArtifact + +from attrs import Factory, define, field + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.drivers import BaseWebSearchDriver from griptape.utils import import_optional_dependency diff --git a/griptape/drivers/web_search/google_web_search_driver.py b/griptape/drivers/web_search/google_web_search_driver.py index 631170532..16d024f77 100644 --- a/griptape/drivers/web_search/google_web_search_driver.py +++ b/griptape/drivers/web_search/google_web_search_driver.py @@ -1,8 +1,10 @@ +import json + +import requests from attrs import define, field -from griptape.artifacts import TextArtifact, ListArtifact + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.drivers import BaseWebSearchDriver -import requests -import json @define diff --git a/griptape/engines/audio/text_to_speech_engine.py b/griptape/engines/audio/text_to_speech_engine.py index d707c5099..af5d5a494 100644 --- a/griptape/engines/audio/text_to_speech_engine.py +++ b/griptape/engines/audio/text_to_speech_engine.py @@ -1,12 +1,12 @@ from __future__ import annotations -from attrs import define, field - from typing import TYPE_CHECKING +from attrs import define, field + if TYPE_CHECKING: - from griptape.drivers import BaseTextToSpeechDriver from griptape.artifacts.audio_artifact import AudioArtifact + from griptape.drivers import BaseTextToSpeechDriver @define diff --git a/griptape/engines/extraction/base_extraction_engine.py b/griptape/engines/extraction/base_extraction_engine.py index aae56569e..cad3680bd 100644 --- a/griptape/engines/extraction/base_extraction_engine.py +++ b/griptape/engines/extraction/base_extraction_engine.py @@ -1,13 +1,16 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING + from abc import ABC, abstractmethod -from attrs import define, field, Factory +from typing import TYPE_CHECKING, Optional + +from attrs import Factory, define, field + from griptape.chunkers import BaseChunker, TextChunker if TYPE_CHECKING: - from griptape.artifacts import ListArtifact, ErrorArtifact - from griptape.rules import Ruleset + from griptape.artifacts import ErrorArtifact, ListArtifact from griptape.drivers import BasePromptDriver + from griptape.rules import Ruleset @define diff --git a/griptape/engines/extraction/csv_extraction_engine.py b/griptape/engines/extraction/csv_extraction_engine.py index c85d26de2..b3a578064 100644 --- a/griptape/engines/extraction/csv_extraction_engine.py +++ b/griptape/engines/extraction/csv_extraction_engine.py @@ -1,9 +1,12 @@ from __future__ import annotations -from typing import Optional, cast, TYPE_CHECKING + import csv import io -from attrs import field, Factory, define -from griptape.artifacts import TextArtifact, CsvRowArtifact, ListArtifact, ErrorArtifact +from typing import TYPE_CHECKING, Optional, cast + +from attrs import Factory, define, field + +from griptape.artifacts import CsvRowArtifact, ErrorArtifact, ListArtifact, TextArtifact from griptape.common import PromptStack from griptape.common.prompt_stack.messages.message import Message from griptape.engines import BaseExtractionEngine diff --git a/griptape/engines/extraction/json_extraction_engine.py b/griptape/engines/extraction/json_extraction_engine.py index 13f6f58bb..2662f28c3 100644 --- a/griptape/engines/extraction/json_extraction_engine.py +++ b/griptape/engines/extraction/json_extraction_engine.py @@ -1,12 +1,15 @@ from __future__ import annotations -from typing import Optional, cast, TYPE_CHECKING + import json -from attrs import field, Factory, define -from griptape.artifacts import TextArtifact, ListArtifact, ErrorArtifact +from typing import TYPE_CHECKING, Optional, cast + +from attrs import Factory, define, field + +from griptape.artifacts import ErrorArtifact, ListArtifact, TextArtifact +from griptape.common import PromptStack from griptape.common.prompt_stack.messages.message import Message from griptape.engines import BaseExtractionEngine from griptape.utils import J2 -from griptape.common import PromptStack if TYPE_CHECKING: from griptape.rules import Ruleset diff --git a/griptape/engines/image/base_image_generation_engine.py b/griptape/engines/image/base_image_generation_engine.py index 5fcf45544..47a853871 100644 --- a/griptape/engines/image/base_image_generation_engine.py +++ b/griptape/engines/image/base_image_generation_engine.py @@ -1,13 +1,13 @@ from __future__ import annotations -from abc import ABC, abstractmethod -from attrs import field, define -from typing import Optional, TYPE_CHECKING +from abc import ABC, abstractmethod +from typing import TYPE_CHECKING, Optional +from attrs import define, field if TYPE_CHECKING: - from griptape.drivers import BaseImageGenerationDriver from griptape.artifacts import ImageArtifact + from griptape.drivers import BaseImageGenerationDriver from griptape.rules import Ruleset diff --git a/griptape/engines/image/inpainting_image_generation_engine.py b/griptape/engines/image/inpainting_image_generation_engine.py index 527cb4eb6..63f91af2e 100644 --- a/griptape/engines/image/inpainting_image_generation_engine.py +++ b/griptape/engines/image/inpainting_image_generation_engine.py @@ -1,13 +1,14 @@ from __future__ import annotations +from typing import TYPE_CHECKING, Optional + from attrs import define -from typing import Optional, TYPE_CHECKING from griptape.engines import BaseImageGenerationEngine if TYPE_CHECKING: - from griptape.rules import Ruleset from griptape.artifacts import ImageArtifact + from griptape.rules import Ruleset @define diff --git a/griptape/engines/image/outpainting_image_generation_engine.py b/griptape/engines/image/outpainting_image_generation_engine.py index 46feed614..4ede5044a 100644 --- a/griptape/engines/image/outpainting_image_generation_engine.py +++ b/griptape/engines/image/outpainting_image_generation_engine.py @@ -1,7 +1,8 @@ from __future__ import annotations +from typing import TYPE_CHECKING, Optional + from attrs import define -from typing import Optional, TYPE_CHECKING from griptape.engines import BaseImageGenerationEngine diff --git a/griptape/engines/image/prompt_image_generation_engine.py b/griptape/engines/image/prompt_image_generation_engine.py index d58ab74b9..742ba4b97 100644 --- a/griptape/engines/image/prompt_image_generation_engine.py +++ b/griptape/engines/image/prompt_image_generation_engine.py @@ -1,13 +1,14 @@ from __future__ import annotations +from typing import TYPE_CHECKING, Optional + from attrs import define -from typing import Optional, TYPE_CHECKING from griptape.engines import BaseImageGenerationEngine if TYPE_CHECKING: - from griptape.rules import Ruleset from griptape.artifacts import ImageArtifact + from griptape.rules import Ruleset @define diff --git a/griptape/engines/image/variation_image_generation_engine.py b/griptape/engines/image/variation_image_generation_engine.py index 89dfadda1..fa182a40b 100644 --- a/griptape/engines/image/variation_image_generation_engine.py +++ b/griptape/engines/image/variation_image_generation_engine.py @@ -1,13 +1,14 @@ from __future__ import annotations +from typing import TYPE_CHECKING, Optional + from attrs import define -from typing import Optional, TYPE_CHECKING from griptape.engines import BaseImageGenerationEngine if TYPE_CHECKING: - from griptape.rules import Ruleset from griptape.artifacts import ImageArtifact + from griptape.rules import Ruleset @define diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py index 9bdcb6372..527fa8ad6 100644 --- a/griptape/engines/rag/modules/base_rag_module.py +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -1,9 +1,11 @@ from abc import ABC from concurrent import futures -from typing import Callable, Any, Optional -from attrs import define, field, Factory +from typing import Any, Callable, Optional + +from attrs import Factory, define, field + +from griptape.common import Message, PromptStack from griptape.engines.rag import RagContext -from griptape.common import PromptStack, Message @define(kw_only=True) diff --git a/griptape/engines/rag/modules/query/base_query_rag_module.py b/griptape/engines/rag/modules/query/base_query_rag_module.py index 195bba6bd..11333c784 100644 --- a/griptape/engines/rag/modules/query/base_query_rag_module.py +++ b/griptape/engines/rag/modules/query/base_query_rag_module.py @@ -1,5 +1,7 @@ from abc import ABC, abstractmethod + from attrs import define + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRagModule diff --git a/griptape/engines/rag/modules/response/base_after_response_rag_module.py b/griptape/engines/rag/modules/response/base_after_response_rag_module.py index 03d906204..3e05c967d 100644 --- a/griptape/engines/rag/modules/response/base_after_response_rag_module.py +++ b/griptape/engines/rag/modules/response/base_after_response_rag_module.py @@ -1,5 +1,7 @@ from abc import ABC, abstractmethod + from attrs import define + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRagModule diff --git a/griptape/engines/rag/modules/response/base_before_response_rag_module.py b/griptape/engines/rag/modules/response/base_before_response_rag_module.py index 2a16b68d0..f1b6ca76d 100644 --- a/griptape/engines/rag/modules/response/base_before_response_rag_module.py +++ b/griptape/engines/rag/modules/response/base_before_response_rag_module.py @@ -1,5 +1,7 @@ from abc import ABC, abstractmethod + from attrs import define + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRagModule diff --git a/griptape/engines/rag/modules/response/base_response_rag_module.py b/griptape/engines/rag/modules/response/base_response_rag_module.py index 72a7dce1b..30ab82201 100644 --- a/griptape/engines/rag/modules/response/base_response_rag_module.py +++ b/griptape/engines/rag/modules/response/base_response_rag_module.py @@ -1,5 +1,7 @@ from abc import ABC, abstractmethod + from attrs import define + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRagModule diff --git a/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py index 7bd1cf0a9..7e88a3a8a 100644 --- a/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py +++ b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py @@ -1,5 +1,7 @@ from typing import Optional + from attrs import define, field + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseBeforeResponseRagModule from griptape.utils import J2 diff --git a/griptape/engines/rag/modules/response/prompt_response_rag_module.py b/griptape/engines/rag/modules/response/prompt_response_rag_module.py index 8552ab904..915b430d8 100644 --- a/griptape/engines/rag/modules/response/prompt_response_rag_module.py +++ b/griptape/engines/rag/modules/response/prompt_response_rag_module.py @@ -1,5 +1,7 @@ from typing import Callable -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.artifacts.text_artifact import TextArtifact from griptape.drivers import BasePromptDriver from griptape.engines.rag import RagContext diff --git a/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py index 27a421c1b..eb22807a6 100644 --- a/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py +++ b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py @@ -1,4 +1,5 @@ from attrs import define, field + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseBeforeResponseRagModule from griptape.rules import Ruleset diff --git a/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py b/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py index 699aa1124..fd57b3905 100644 --- a/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py +++ b/griptape/engines/rag/modules/response/text_chunks_response_rag_module.py @@ -1,4 +1,5 @@ from attrs import define + from griptape.artifacts import ListArtifact from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseResponseRagModule diff --git a/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py b/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py index 8ecf9f046..84a7565d4 100644 --- a/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/base_rerank_rag_module.py @@ -1,7 +1,8 @@ from abc import ABC, abstractmethod -from typing import Sequence +from collections.abc import Sequence from attrs import define, field + from griptape.artifacts import BaseArtifact from griptape.drivers import BaseRerankDriver from griptape.engines.rag import RagContext diff --git a/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py index f11537d9f..fbeb216f2 100644 --- a/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/base_retrieval_rag_module.py @@ -1,6 +1,8 @@ from abc import ABC, abstractmethod -from typing import Sequence +from collections.abc import Sequence + from attrs import define + from griptape.artifacts import BaseArtifact from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRagModule diff --git a/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py b/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py index b78c3a880..c0256847e 100644 --- a/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/text_chunks_rerank_rag_module.py @@ -1,6 +1,7 @@ -from typing import Sequence +from collections.abc import Sequence from attrs import define + from griptape.artifacts import BaseArtifact from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRerankRagModule diff --git a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py index 248f69af2..7ae5df226 100644 --- a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py @@ -1,15 +1,19 @@ from __future__ import annotations + import uuid from typing import TYPE_CHECKING, Any, Callable -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape import utils -from griptape.artifacts import TextArtifact, ErrorArtifact +from griptape.artifacts import ErrorArtifact, TextArtifact from griptape.engines.rag.modules import BaseRetrievalRagModule if TYPE_CHECKING: from collections.abc import Sequence - from griptape.engines.rag import RagContext + from griptape.drivers import BaseVectorStoreDriver + from griptape.engines.rag import RagContext from griptape.loaders import BaseTextLoader diff --git a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py index 00d709346..cbe5e6852 100644 --- a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py @@ -1,14 +1,18 @@ from __future__ import annotations + from typing import TYPE_CHECKING, Any, Callable -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape import utils from griptape.engines.rag.modules import BaseRetrievalRagModule if TYPE_CHECKING: from collections.abc import Sequence - from griptape.engines.rag import RagContext + from griptape.artifacts import TextArtifact from griptape.drivers import BaseVectorStoreDriver + from griptape.engines.rag import RagContext @define(kw_only=True) diff --git a/griptape/engines/rag/rag_context.py b/griptape/engines/rag/rag_context.py index be4807599..1b0496d72 100644 --- a/griptape/engines/rag/rag_context.py +++ b/griptape/engines/rag/rag_context.py @@ -1,13 +1,15 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING + +from typing import TYPE_CHECKING, Optional + from attrs import define, field from griptape import utils from griptape.mixins import SerializableMixin if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact, TextArtifact from griptape.common import Reference - from griptape.artifacts import TextArtifact, BaseArtifact @define(kw_only=True) diff --git a/griptape/engines/rag/rag_engine.py b/griptape/engines/rag/rag_engine.py index da8a2eebe..9fdb13384 100644 --- a/griptape/engines/rag/rag_engine.py +++ b/griptape/engines/rag/rag_engine.py @@ -1,5 +1,7 @@ from typing import Optional + from attrs import define, field + from griptape.engines.rag import RagContext from griptape.engines.rag.stages import QueryRagStage, ResponseRagStage, RetrievalRagStage diff --git a/griptape/engines/rag/stages/base_rag_stage.py b/griptape/engines/rag/stages/base_rag_stage.py index 4db996e30..8c94405e0 100644 --- a/griptape/engines/rag/stages/base_rag_stage.py +++ b/griptape/engines/rag/stages/base_rag_stage.py @@ -1,7 +1,9 @@ from abc import ABC, abstractmethod from concurrent import futures from typing import Callable -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseRagModule diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py index 84c200bc8..35f5df371 100644 --- a/griptape/engines/rag/stages/query_rag_stage.py +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -1,5 +1,7 @@ import logging + from attrs import define, field + from griptape import utils from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseQueryRagModule, BaseRagModule diff --git a/griptape/engines/rag/stages/response_rag_stage.py b/griptape/engines/rag/stages/response_rag_stage.py index aa0a15dfc..d6467bbb5 100644 --- a/griptape/engines/rag/stages/response_rag_stage.py +++ b/griptape/engines/rag/stages/response_rag_stage.py @@ -1,11 +1,13 @@ import logging + from attrs import define, field + from griptape.engines.rag import RagContext from griptape.engines.rag.modules import ( - BaseResponseRagModule, - BaseBeforeResponseRagModule, BaseAfterResponseRagModule, + BaseBeforeResponseRagModule, BaseRagModule, + BaseResponseRagModule, ) from griptape.engines.rag.stages import BaseRagStage diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py index 8fe376cd1..f65d92f57 100644 --- a/griptape/engines/rag/stages/retrieval_rag_stage.py +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -1,12 +1,13 @@ import itertools import logging from typing import Optional + from attrs import define, field + from griptape import utils from griptape.artifacts import TextArtifact from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseRerankRagModule, BaseRagModule -from griptape.engines.rag.modules import BaseRetrievalRagModule +from griptape.engines.rag.modules import BaseRagModule, BaseRerankRagModule, BaseRetrievalRagModule from griptape.engines.rag.stages import BaseRagStage diff --git a/griptape/engines/summary/base_summary_engine.py b/griptape/engines/summary/base_summary_engine.py index 26a5cd46d..108666bb7 100644 --- a/griptape/engines/summary/base_summary_engine.py +++ b/griptape/engines/summary/base_summary_engine.py @@ -1,7 +1,9 @@ from abc import ABC, abstractmethod from typing import Optional + from attrs import define -from griptape.artifacts import TextArtifact, ListArtifact + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.rules import Ruleset diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 51259e444..01823ed08 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -1,13 +1,15 @@ from typing import Optional, cast -from attrs import define, Factory, field -from griptape.artifacts import TextArtifact, ListArtifact + +from attrs import Factory, define, field + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.chunkers import BaseChunker, TextChunker from griptape.common import PromptStack from griptape.common.prompt_stack.messages.message import Message from griptape.drivers import BasePromptDriver from griptape.engines import BaseSummaryEngine -from griptape.utils import J2 from griptape.rules import Ruleset +from griptape.utils import J2 @define diff --git a/griptape/events/base_actions_subtask_event.py b/griptape/events/base_actions_subtask_event.py index cfd900000..d8dd0fd4a 100644 --- a/griptape/events/base_actions_subtask_event.py +++ b/griptape/events/base_actions_subtask_event.py @@ -1,7 +1,10 @@ from __future__ import annotations + from abc import ABC -from attrs import define, field from typing import TYPE_CHECKING, Optional + +from attrs import define, field + from .base_task_event import BaseTaskEvent if TYPE_CHECKING: diff --git a/griptape/events/base_image_generation_event.py b/griptape/events/base_image_generation_event.py index 5cc516b8e..c951cf64a 100644 --- a/griptape/events/base_image_generation_event.py +++ b/griptape/events/base_image_generation_event.py @@ -1,6 +1,9 @@ from __future__ import annotations -from attrs import define + from abc import ABC + +from attrs import define + from .base_media_generation_event import BaseMediaGenerationEvent diff --git a/griptape/events/base_media_generation_event.py b/griptape/events/base_media_generation_event.py index 0280c41aa..8d54169a4 100644 --- a/griptape/events/base_media_generation_event.py +++ b/griptape/events/base_media_generation_event.py @@ -1,6 +1,9 @@ from __future__ import annotations -from attrs import define + from abc import ABC + +from attrs import define + from .base_event import BaseEvent diff --git a/griptape/events/base_prompt_event.py b/griptape/events/base_prompt_event.py index 4a44599cc..19490de5f 100644 --- a/griptape/events/base_prompt_event.py +++ b/griptape/events/base_prompt_event.py @@ -1,6 +1,9 @@ from __future__ import annotations -from attrs import define, field + from abc import ABC + +from attrs import define, field + from .base_event import BaseEvent diff --git a/griptape/events/base_task_event.py b/griptape/events/base_task_event.py index c486d3f75..ab4fddb2a 100644 --- a/griptape/events/base_task_event.py +++ b/griptape/events/base_task_event.py @@ -1,7 +1,10 @@ from __future__ import annotations -from attrs import define, field + from abc import ABC -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional + +from attrs import define, field + from .base_event import BaseEvent if TYPE_CHECKING: diff --git a/griptape/events/base_text_to_speech_event.py b/griptape/events/base_text_to_speech_event.py index d73b3a663..6fa9d9ce0 100644 --- a/griptape/events/base_text_to_speech_event.py +++ b/griptape/events/base_text_to_speech_event.py @@ -1,7 +1,9 @@ from __future__ import annotations -from attrs import define + from abc import ABC +from attrs import define + from griptape.events.base_media_generation_event import BaseMediaGenerationEvent diff --git a/griptape/events/completion_chunk_event.py b/griptape/events/completion_chunk_event.py index a4244bd5d..48b479625 100644 --- a/griptape/events/completion_chunk_event.py +++ b/griptape/events/completion_chunk_event.py @@ -1,5 +1,5 @@ -from attrs import field -from attrs import define +from attrs import define, field + from griptape.events.base_event import BaseEvent diff --git a/griptape/events/event_listener.py b/griptape/events/event_listener.py index 1aad6ffc5..aee850e08 100644 --- a/griptape/events/event_listener.py +++ b/griptape/events/event_listener.py @@ -1,11 +1,14 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING, Callable -from attrs import define, field, Factory + +from typing import TYPE_CHECKING, Callable, Optional + +from attrs import Factory, define, field if TYPE_CHECKING: - from .base_event import BaseEvent from griptape.drivers import BaseEventListenerDriver + from .base_event import BaseEvent + @define class EventListener: diff --git a/griptape/events/finish_actions_subtask_event.py b/griptape/events/finish_actions_subtask_event.py index 068efca0b..772ac36ae 100644 --- a/griptape/events/finish_actions_subtask_event.py +++ b/griptape/events/finish_actions_subtask_event.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define + from .base_actions_subtask_event import BaseActionsSubtaskEvent diff --git a/griptape/events/finish_prompt_event.py b/griptape/events/finish_prompt_event.py index 79e338871..25f658a0f 100644 --- a/griptape/events/finish_prompt_event.py +++ b/griptape/events/finish_prompt_event.py @@ -1,5 +1,7 @@ -from attrs import define, field from typing import Optional + +from attrs import define, field + from griptape.events.base_prompt_event import BasePromptEvent diff --git a/griptape/events/finish_task_event.py b/griptape/events/finish_task_event.py index 65b2ca4f2..f83f98c04 100644 --- a/griptape/events/finish_task_event.py +++ b/griptape/events/finish_task_event.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define + from .base_task_event import BaseTaskEvent diff --git a/griptape/events/start_actions_subtask_event.py b/griptape/events/start_actions_subtask_event.py index eb3827daf..e688ef1c3 100644 --- a/griptape/events/start_actions_subtask_event.py +++ b/griptape/events/start_actions_subtask_event.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define + from .base_actions_subtask_event import BaseActionsSubtaskEvent diff --git a/griptape/events/start_image_generation_event.py b/griptape/events/start_image_generation_event.py index c673f34c4..d5b5a9805 100644 --- a/griptape/events/start_image_generation_event.py +++ b/griptape/events/start_image_generation_event.py @@ -1,6 +1,7 @@ from __future__ import annotations from typing import Optional + from attrs import define, field from .base_image_generation_event import BaseImageGenerationEvent diff --git a/griptape/events/start_prompt_event.py b/griptape/events/start_prompt_event.py index 35dae95d6..ca3958f89 100644 --- a/griptape/events/start_prompt_event.py +++ b/griptape/events/start_prompt_event.py @@ -1,7 +1,9 @@ from __future__ import annotations + from typing import TYPE_CHECKING -from attrs import define -from attrs import field + +from attrs import define, field + from griptape.events.base_prompt_event import BasePromptEvent if TYPE_CHECKING: diff --git a/griptape/events/start_task_event.py b/griptape/events/start_task_event.py index bd4661c2f..699d42a17 100644 --- a/griptape/events/start_task_event.py +++ b/griptape/events/start_task_event.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define + from .base_task_event import BaseTaskEvent diff --git a/griptape/loaders/base_loader.py b/griptape/loaders/base_loader.py index d2448d103..f9fa5d4bc 100644 --- a/griptape/loaders/base_loader.py +++ b/griptape/loaders/base_loader.py @@ -2,15 +2,16 @@ from abc import ABC, abstractmethod from concurrent import futures -from typing import Any, Optional, Callable, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, Callable, Optional -from attrs import define, field, Factory +from attrs import Factory, define, field from griptape.utils.futures import execute_futures_dict from griptape.utils.hash import bytes_to_hash, str_to_hash if TYPE_CHECKING: from collections.abc import Mapping, Sequence + from griptape.artifacts import BaseArtifact diff --git a/griptape/loaders/base_text_loader.py b/griptape/loaders/base_text_loader.py index 58787c881..eac16ab91 100644 --- a/griptape/loaders/base_text_loader.py +++ b/griptape/loaders/base_text_loader.py @@ -1,10 +1,13 @@ from __future__ import annotations + from abc import ABC, abstractmethod -from typing import Any, Optional, Union, cast, TYPE_CHECKING -from attrs import define, field, Factory +from typing import TYPE_CHECKING, Any, Optional, Union, cast + +from attrs import Factory, define, field + from griptape.artifacts import TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact -from griptape.chunkers import TextChunker, BaseChunker +from griptape.chunkers import BaseChunker, TextChunker from griptape.loaders import BaseLoader from griptape.tokenizers import OpenAiTokenizer diff --git a/griptape/loaders/blob_loader.py b/griptape/loaders/blob_loader.py index 8b9ea4bf9..fffabb849 100644 --- a/griptape/loaders/blob_loader.py +++ b/griptape/loaders/blob_loader.py @@ -1,4 +1,5 @@ from __future__ import annotations + from typing import Any, Union, cast from attrs import define diff --git a/griptape/loaders/csv_loader.py b/griptape/loaders/csv_loader.py index 21ca1f5a6..435ecb873 100644 --- a/griptape/loaders/csv_loader.py +++ b/griptape/loaders/csv_loader.py @@ -1,7 +1,8 @@ from __future__ import annotations + import csv from io import StringIO -from typing import Optional, Union, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional, Union, cast from attrs import define, field diff --git a/griptape/loaders/dataframe_loader.py b/griptape/loaders/dataframe_loader.py index a547ab7cc..0b1ae1448 100644 --- a/griptape/loaders/dataframe_loader.py +++ b/griptape/loaders/dataframe_loader.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING, cast +from typing import TYPE_CHECKING, Optional, cast from attrs import define, field @@ -10,9 +10,10 @@ from griptape.utils.hash import str_to_hash if TYPE_CHECKING: - from griptape.drivers import BaseEmbeddingDriver from pandas import DataFrame + from griptape.drivers import BaseEmbeddingDriver + @define class DataFrameLoader(BaseLoader): diff --git a/griptape/loaders/email_loader.py b/griptape/loaders/email_loader.py index 3d0ad1358..e13558ab3 100644 --- a/griptape/loaders/email_loader.py +++ b/griptape/loaders/email_loader.py @@ -1,14 +1,14 @@ from __future__ import annotations -from typing import Optional, Union, cast -import logging import imaplib +import logging +from typing import Optional, Union, cast from attrs import astuple, define, field -from griptape.utils import import_optional_dependency from griptape.artifacts import ErrorArtifact, ListArtifact, TextArtifact from griptape.loaders import BaseLoader +from griptape.utils import import_optional_dependency @define diff --git a/griptape/loaders/image_loader.py b/griptape/loaders/image_loader.py index ca0ba776a..90048abc1 100644 --- a/griptape/loaders/image_loader.py +++ b/griptape/loaders/image_loader.py @@ -5,9 +5,9 @@ from attrs import define, field -from griptape.utils import import_optional_dependency from griptape.artifacts import ImageArtifact from griptape.loaders import BaseLoader +from griptape.utils import import_optional_dependency @define diff --git a/griptape/loaders/pdf_loader.py b/griptape/loaders/pdf_loader.py index 8e4560cfc..d0622a9b4 100644 --- a/griptape/loaders/pdf_loader.py +++ b/griptape/loaders/pdf_loader.py @@ -1,14 +1,15 @@ from __future__ import annotations -from io import BytesIO -from attrs import define, field, Factory +from io import BytesIO from typing import Optional, Union, cast +from attrs import Factory, define, field + +from griptape.artifacts import TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact +from griptape.chunkers import PdfChunker from griptape.loaders import BaseTextLoader from griptape.utils import import_optional_dependency -from griptape.artifacts import TextArtifact -from griptape.chunkers import PdfChunker @define diff --git a/griptape/loaders/sql_loader.py b/griptape/loaders/sql_loader.py index e6979e324..2ac621a82 100644 --- a/griptape/loaders/sql_loader.py +++ b/griptape/loaders/sql_loader.py @@ -3,7 +3,7 @@ from attrs import define, field from griptape.artifacts import CsvRowArtifact -from griptape.drivers import BaseSqlDriver, BaseEmbeddingDriver +from griptape.drivers import BaseEmbeddingDriver, BaseSqlDriver from griptape.loaders import BaseLoader diff --git a/griptape/loaders/text_loader.py b/griptape/loaders/text_loader.py index 2dfa3bbe9..8eaa0b110 100644 --- a/griptape/loaders/text_loader.py +++ b/griptape/loaders/text_loader.py @@ -1,8 +1,8 @@ from __future__ import annotations -from typing import Optional, Union, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional, Union, cast -from attrs import field, define, Factory +from attrs import Factory, define, field from griptape.artifacts import TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact diff --git a/griptape/loaders/web_loader.py b/griptape/loaders/web_loader.py index bde2ec305..e7265bba2 100644 --- a/griptape/loaders/web_loader.py +++ b/griptape/loaders/web_loader.py @@ -1,9 +1,12 @@ from __future__ import annotations -from attrs import define, field, Factory + +from typing import TYPE_CHECKING + +from attrs import Factory, define, field + from griptape.artifacts.error_artifact import ErrorArtifact from griptape.drivers import BaseWebScraperDriver, TrafilaturaWebScraperDriver from griptape.loaders import BaseTextLoader -from typing import TYPE_CHECKING if TYPE_CHECKING: from griptape.artifacts import TextArtifact diff --git a/griptape/memory/meta/action_subtask_meta_entry.py b/griptape/memory/meta/action_subtask_meta_entry.py index 6b5124971..10920ae20 100644 --- a/griptape/memory/meta/action_subtask_meta_entry.py +++ b/griptape/memory/meta/action_subtask_meta_entry.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import Optional -from attrs import field, define + +from attrs import define, field + from griptape.memory.meta import BaseMetaEntry diff --git a/griptape/memory/meta/base_meta_entry.py b/griptape/memory/meta/base_meta_entry.py index c79ec4731..c1b253317 100644 --- a/griptape/memory/meta/base_meta_entry.py +++ b/griptape/memory/meta/base_meta_entry.py @@ -1,7 +1,9 @@ from __future__ import annotations -from attrs import define + from abc import ABC +from attrs import define + from griptape.mixins import SerializableMixin diff --git a/griptape/memory/meta/meta_memory.py b/griptape/memory/meta/meta_memory.py index 214e6e285..2c580de28 100644 --- a/griptape/memory/meta/meta_memory.py +++ b/griptape/memory/meta/meta_memory.py @@ -1,4 +1,5 @@ from attrs import define, field + from griptape.memory.meta import BaseMetaEntry diff --git a/griptape/memory/structure/base_conversation_memory.py b/griptape/memory/structure/base_conversation_memory.py index e68939026..5d52eb4ad 100644 --- a/griptape/memory/structure/base_conversation_memory.py +++ b/griptape/memory/structure/base_conversation_memory.py @@ -1,13 +1,16 @@ from __future__ import annotations + +from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Optional + from attrs import define, field + from griptape.common import PromptStack from griptape.mixins import SerializableMixin -from abc import ABC, abstractmethod if TYPE_CHECKING: - from griptape.memory.structure import Run from griptape.drivers import BaseConversationMemoryDriver + from griptape.memory.structure import Run from griptape.structures import Structure diff --git a/griptape/memory/structure/conversation_memory.py b/griptape/memory/structure/conversation_memory.py index 42d160abd..34f96e414 100644 --- a/griptape/memory/structure/conversation_memory.py +++ b/griptape/memory/structure/conversation_memory.py @@ -1,8 +1,11 @@ from __future__ import annotations -from attrs import define + from typing import Optional -from griptape.memory.structure import Run, BaseConversationMemory + +from attrs import define + from griptape.common import PromptStack +from griptape.memory.structure import BaseConversationMemory, Run @define diff --git a/griptape/memory/structure/run.py b/griptape/memory/structure/run.py index b91df2ae9..3d8ca3869 100644 --- a/griptape/memory/structure/run.py +++ b/griptape/memory/structure/run.py @@ -1,5 +1,7 @@ import uuid -from attrs import define, field, Factory + +from attrs import Factory, define, field + from griptape.artifacts.base_artifact import BaseArtifact from griptape.mixins import SerializableMixin diff --git a/griptape/memory/structure/summary_conversation_memory.py b/griptape/memory/structure/summary_conversation_memory.py index b88a4b4e6..5854aa058 100644 --- a/griptape/memory/structure/summary_conversation_memory.py +++ b/griptape/memory/structure/summary_conversation_memory.py @@ -1,11 +1,14 @@ from __future__ import annotations + import logging from typing import TYPE_CHECKING, Optional -from attrs import define, field, Factory -from griptape.common.prompt_stack.messages.message import Message -from griptape.utils import J2 + +from attrs import Factory, define, field + from griptape.common import PromptStack +from griptape.common.prompt_stack.messages.message import Message from griptape.memory.structure import ConversationMemory +from griptape.utils import J2 if TYPE_CHECKING: from griptape.drivers import BasePromptDriver diff --git a/griptape/memory/task/storage/base_artifact_storage.py b/griptape/memory/task/storage/base_artifact_storage.py index e6ec68797..866df19da 100644 --- a/griptape/memory/task/storage/base_artifact_storage.py +++ b/griptape/memory/task/storage/base_artifact_storage.py @@ -1,10 +1,12 @@ from __future__ import annotations -from typing import Any, TYPE_CHECKING + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING, Any + from attrs import define if TYPE_CHECKING: - from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact, InfoArtifact + from griptape.artifacts import BaseArtifact, InfoArtifact, ListArtifact, TextArtifact @define diff --git a/griptape/memory/task/storage/blob_artifact_storage.py b/griptape/memory/task/storage/blob_artifact_storage.py index 9d09e17fa..25706c079 100644 --- a/griptape/memory/task/storage/blob_artifact_storage.py +++ b/griptape/memory/task/storage/blob_artifact_storage.py @@ -1,6 +1,8 @@ from typing import Any + from attrs import define, field -from griptape.artifacts import BaseArtifact, ListArtifact, BlobArtifact, InfoArtifact + +from griptape.artifacts import BaseArtifact, BlobArtifact, InfoArtifact, ListArtifact from griptape.memory.task.storage import BaseArtifactStorage diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 51994fa6c..f6bcf93d5 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -1,8 +1,11 @@ from __future__ import annotations + from typing import TYPE_CHECKING, Any, Optional + from attrs import define, field -from griptape.artifacts import TextArtifact, BaseArtifact, ListArtifact, InfoArtifact -from griptape.engines.rag import RagEngine, RagContext + +from griptape.artifacts import BaseArtifact, InfoArtifact, ListArtifact, TextArtifact +from griptape.engines.rag import RagContext, RagEngine from griptape.memory.task.storage import BaseArtifactStorage if TYPE_CHECKING: diff --git a/griptape/memory/task/task_memory.py b/griptape/memory/task/task_memory.py index df9c9be30..2c3075576 100644 --- a/griptape/memory/task/task_memory.py +++ b/griptape/memory/task/task_memory.py @@ -1,7 +1,10 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Any, Callable -from attrs import define, field, Factory -from griptape.artifacts import BaseArtifact, InfoArtifact, ListArtifact, ErrorArtifact, TextArtifact + +from typing import TYPE_CHECKING, Any, Callable, Optional + +from attrs import Factory, define, field + +from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.memory.meta import ActionSubtaskMetaEntry from griptape.mixins import ActivityMixin diff --git a/griptape/mixins/actions_subtask_origin_mixin.py b/griptape/mixins/actions_subtask_origin_mixin.py index 22f06a1c6..eba3637e5 100644 --- a/griptape/mixins/actions_subtask_origin_mixin.py +++ b/griptape/mixins/actions_subtask_origin_mixin.py @@ -1,13 +1,15 @@ from __future__ import annotations -from typing import TYPE_CHECKING + from abc import abstractmethod +from typing import TYPE_CHECKING + from attrs import define -from schema import Schema, Literal +from schema import Literal, Schema if TYPE_CHECKING: from griptape.memory import TaskMemory - from griptape.tools import BaseTool from griptape.tasks import ActionsSubtask + from griptape.tools import BaseTool @define(slots=False) diff --git a/griptape/mixins/activity_mixin.py b/griptape/mixins/activity_mixin.py index 9dc605543..31f398482 100644 --- a/griptape/mixins/activity_mixin.py +++ b/griptape/mixins/activity_mixin.py @@ -1,9 +1,10 @@ import inspect -from typing import Optional, Callable +from typing import Callable, Optional + +import schema from attrs import define, field from jinja2 import Template -import schema -from schema import Schema, Literal +from schema import Literal, Schema @define(slots=False) diff --git a/griptape/mixins/exponential_backoff_mixin.py b/griptape/mixins/exponential_backoff_mixin.py index 5045575f1..fb17a3400 100644 --- a/griptape/mixins/exponential_backoff_mixin.py +++ b/griptape/mixins/exponential_backoff_mixin.py @@ -1,9 +1,10 @@ import logging from abc import ABC -from attrs import define, field -from tenacity import Retrying, wait_exponential, stop_after_attempt, retry_if_not_exception_type from typing import Callable +from attrs import define, field +from tenacity import Retrying, retry_if_not_exception_type, stop_after_attempt, wait_exponential + @define(slots=False) class ExponentialBackoffMixin(ABC): diff --git a/griptape/mixins/media_artifact_file_output_mixin.py b/griptape/mixins/media_artifact_file_output_mixin.py index 14dcd4898..b2a0d8ef9 100644 --- a/griptape/mixins/media_artifact_file_output_mixin.py +++ b/griptape/mixins/media_artifact_file_output_mixin.py @@ -1,10 +1,9 @@ from __future__ import annotations import os -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Optional from attrs import define, field -from typing import Optional if TYPE_CHECKING: from griptape.artifacts import BlobArtifact diff --git a/griptape/mixins/rule_mixin.py b/griptape/mixins/rule_mixin.py index 0cc696242..04a487505 100644 --- a/griptape/mixins/rule_mixin.py +++ b/griptape/mixins/rule_mixin.py @@ -4,7 +4,7 @@ from attrs import define, field -from griptape.rules import Ruleset, Rule +from griptape.rules import Rule, Ruleset if TYPE_CHECKING: from griptape.structures import Structure diff --git a/griptape/mixins/serializable_mixin.py b/griptape/mixins/serializable_mixin.py index 2364e8bc4..e8f772cab 100644 --- a/griptape/mixins/serializable_mixin.py +++ b/griptape/mixins/serializable_mixin.py @@ -1,13 +1,13 @@ from __future__ import annotations import json -from typing import TypeVar, Generic, cast, Optional, TYPE_CHECKING +from abc import ABC +from importlib import import_module +from typing import TYPE_CHECKING, Generic, Optional, TypeVar, cast from attrs import Factory, define, field -from abc import ABC from griptape.schemas.base_schema import BaseSchema -from importlib import import_module if TYPE_CHECKING: from marshmallow import Schema diff --git a/griptape/rules/rule.py b/griptape/rules/rule.py index f2a33c7e5..1063d174e 100644 --- a/griptape/rules/rule.py +++ b/griptape/rules/rule.py @@ -1,4 +1,5 @@ from __future__ import annotations + from attrs import define diff --git a/griptape/rules/ruleset.py b/griptape/rules/ruleset.py index 9a78b58b8..5d2cca62a 100644 --- a/griptape/rules/ruleset.py +++ b/griptape/rules/ruleset.py @@ -1,4 +1,5 @@ -from attrs import field, define +from attrs import define, field + from griptape.rules import Rule diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index cfc9c2f5c..15dd96b5d 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -1,11 +1,11 @@ from __future__ import annotations from abc import ABC -from typing import Union, Literal, get_args, get_origin from collections.abc import Sequence +from typing import Literal, Union, get_args, get_origin import attrs -from marshmallow import Schema, fields, INCLUDE +from marshmallow import INCLUDE, Schema, fields from griptape.schemas.bytes_field import Bytes @@ -24,6 +24,7 @@ def from_attrs_cls(cls, attrs_cls: type) -> type: attrs_cls: An attrs class. """ from marshmallow import post_load + from griptape.mixins import SerializableMixin class SubSchema(cls): @@ -100,33 +101,34 @@ def _resolve_types(cls, attrs_cls: type) -> None: Args: attrs_cls: An attrs class. """ - from griptape.utils.import_utils import import_optional_dependency, is_dependency_installed + from typing import Any + + from griptape.artifacts import BaseArtifact + from griptape.common import ( + BaseDeltaMessageContent, + BaseMessageContent, + Message, + PromptStack, + Reference, + ToolAction, + ) # These modules are required to avoid `NameError`s when resolving types. from griptape.drivers import ( + BaseAudioTranscriptionDriver, BaseConversationMemoryDriver, - BasePromptDriver, + BaseEmbeddingDriver, BaseImageGenerationDriver, BaseImageQueryDriver, - BaseEmbeddingDriver, - BaseVectorStoreDriver, + BasePromptDriver, BaseTextToSpeechDriver, - BaseAudioTranscriptionDriver, + BaseVectorStoreDriver, ) + from griptape.memory.structure import Run from griptape.structures import Structure - from griptape.common import ( - PromptStack, - Message, - Reference, - ToolAction, - BaseMessageContent, - BaseDeltaMessageContent, - ) from griptape.tokenizers.base_tokenizer import BaseTokenizer from griptape.tools import BaseTool - from griptape.memory.structure import Run - from typing import Any - from griptape.artifacts import BaseArtifact + from griptape.utils.import_utils import import_optional_dependency, is_dependency_installed boto3 = import_optional_dependency("boto3") if is_dependency_installed("boto3") else Any Client = import_optional_dependency("cohere").Client if is_dependency_installed("cohere") else Any diff --git a/griptape/schemas/bytes_field.py b/griptape/schemas/bytes_field.py index 11636e4d5..ac2830388 100644 --- a/griptape/schemas/bytes_field.py +++ b/griptape/schemas/bytes_field.py @@ -1,5 +1,6 @@ import base64 -from marshmallow import fields, ValidationError + +from marshmallow import ValidationError, fields class Bytes(fields.Field): diff --git a/griptape/schemas/polymorphic_schema.py b/griptape/schemas/polymorphic_schema.py index 60001de18..3fd7450ff 100644 --- a/griptape/schemas/polymorphic_schema.py +++ b/griptape/schemas/polymorphic_schema.py @@ -1,5 +1,7 @@ from typing import Any -from marshmallow import ValidationError, Schema + +from marshmallow import Schema, ValidationError + from griptape.schemas import BaseSchema diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 1df541e2a..5d4c3054a 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -1,15 +1,18 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Callable + +from typing import TYPE_CHECKING, Callable, Optional + from attrs import define, field + from griptape.artifacts.text_artifact import TextArtifact from griptape.memory.structure import Run from griptape.structures import Structure from griptape.tasks import PromptTask, ToolkitTask if TYPE_CHECKING: - from griptape.tools import BaseTool from griptape.artifacts import BaseArtifact from griptape.tasks import BaseTask + from griptape.tools import BaseTool @define diff --git a/griptape/structures/pipeline.py b/griptape/structures/pipeline.py index 408a42225..81e9d31fd 100644 --- a/griptape/structures/pipeline.py +++ b/griptape/structures/pipeline.py @@ -1,6 +1,9 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Optional, Any + +from typing import TYPE_CHECKING, Any, Optional + from attrs import define + from griptape.artifacts import ErrorArtifact from griptape.memory.structure import Run from griptape.structures import Structure diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 52098f05f..fb6cd25cd 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -1,24 +1,27 @@ from __future__ import annotations + import logging import uuid from abc import ABC, abstractmethod from logging import Logger from typing import TYPE_CHECKING, Any, Optional + from attrs import Factory, define, field from rich.logging import RichHandler -from griptape.artifacts import BlobArtifact, TextArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, BlobArtifact, TextArtifact from griptape.config import BaseStructureConfig, OpenAiStructureConfig, StructureConfig -from griptape.drivers import BaseEmbeddingDriver, BasePromptDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver +from griptape.drivers import BaseEmbeddingDriver, BasePromptDriver, OpenAiChatPromptDriver, OpenAiEmbeddingDriver from griptape.drivers.vector.local_vector_store_driver import LocalVectorStoreDriver from griptape.engines import CsvExtractionEngine, JsonExtractionEngine, PromptSummaryEngine from griptape.engines.rag import RagEngine from griptape.engines.rag.modules import ( - VectorStoreRetrievalRagModule, - RulesetsBeforeResponseRagModule, - PromptResponseRagModule, MetadataBeforeResponseRagModule, + PromptResponseRagModule, + RulesetsBeforeResponseRagModule, + VectorStoreRetrievalRagModule, ) -from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage +from griptape.engines.rag.stages import ResponseRagStage, RetrievalRagStage from griptape.events.finish_structure_run_event import FinishStructureRunEvent from griptape.events.start_structure_run_event import StartStructureRunEvent from griptape.memory import TaskMemory @@ -28,10 +31,10 @@ from griptape.utils import deprecation_warn if TYPE_CHECKING: - from griptape.rules import Rule, Ruleset from griptape.events import BaseEvent, EventListener - from griptape.tasks import BaseTask from griptape.memory.structure import BaseConversationMemory + from griptape.rules import Rule, Ruleset + from griptape.tasks import BaseTask @define diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 523e5317d..d83dee756 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -1,11 +1,14 @@ from __future__ import annotations + import concurrent.futures as futures +from typing import TYPE_CHECKING, Any, Callable, Optional + +from attrs import Factory, define, field from graphlib import TopologicalSorter -from typing import Any, Optional, Callable, TYPE_CHECKING -from attrs import define, field, Factory + from griptape.artifacts import ErrorArtifact -from griptape.structures import Structure from griptape.memory.structure import Run +from griptape.structures import Structure if TYPE_CHECKING: from griptape.tasks import BaseTask diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index ba73a29f0..d384acde9 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -1,17 +1,19 @@ from __future__ import annotations + import json import re -from typing import Optional, TYPE_CHECKING, Callable +from typing import TYPE_CHECKING, Callable, Optional import schema from attrs import define, field + from griptape import utils +from griptape.artifacts import ActionArtifact, BaseArtifact, ErrorArtifact, ListArtifact, TextArtifact from griptape.common import ToolAction -from griptape.utils import remove_null_values_in_dict_recursively +from griptape.events import FinishActionsSubtaskEvent, StartActionsSubtaskEvent from griptape.mixins import ActionsSubtaskOriginMixin from griptape.tasks import BaseTask -from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact, ListArtifact, ActionArtifact -from griptape.events import StartActionsSubtaskEvent, FinishActionsSubtaskEvent +from griptape.utils import remove_null_values_in_dict_recursively if TYPE_CHECKING: from griptape.memory import TaskMemory diff --git a/griptape/tasks/audio_transcription_task.py b/griptape/tasks/audio_transcription_task.py index 607911782..cc36f4eae 100644 --- a/griptape/tasks/audio_transcription_task.py +++ b/griptape/tasks/audio_transcription_task.py @@ -1,10 +1,11 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from attrs import define, field from griptape.engines import AudioTranscriptionEngine from griptape.tasks.base_audio_input_task import BaseAudioInputTask -from typing import TYPE_CHECKING if TYPE_CHECKING: from griptape.artifacts import TextArtifact diff --git a/griptape/tasks/base_audio_generation_task.py b/griptape/tasks/base_audio_generation_task.py index 71c2fbdf4..0a730e3b2 100644 --- a/griptape/tasks/base_audio_generation_task.py +++ b/griptape/tasks/base_audio_generation_task.py @@ -4,7 +4,7 @@ from attrs import define -from griptape.mixins import RuleMixin, BlobArtifactFileOutputMixin +from griptape.mixins import BlobArtifactFileOutputMixin, RuleMixin from griptape.tasks import BaseTask diff --git a/griptape/tasks/base_image_generation_task.py b/griptape/tasks/base_image_generation_task.py index 3b8cfb16a..74cf2d04e 100644 --- a/griptape/tasks/base_image_generation_task.py +++ b/griptape/tasks/base_image_generation_task.py @@ -2,14 +2,14 @@ import os from abc import ABC +from typing import TYPE_CHECKING -from attrs import field, define +from attrs import define, field from griptape.loaders import ImageLoader -from griptape.mixins import RuleMixin, BlobArtifactFileOutputMixin -from griptape.rules import Ruleset, Rule +from griptape.mixins import BlobArtifactFileOutputMixin, RuleMixin +from griptape.rules import Rule, Ruleset from griptape.tasks import BaseTask -from typing import TYPE_CHECKING if TYPE_CHECKING: from griptape.artifacts import MediaArtifact diff --git a/griptape/tasks/base_multi_text_input_task.py b/griptape/tasks/base_multi_text_input_task.py index 385bc9b5b..3804a749f 100644 --- a/griptape/tasks/base_multi_text_input_task.py +++ b/griptape/tasks/base_multi_text_input_task.py @@ -3,7 +3,7 @@ from abc import ABC from typing import Callable -from attrs import define, field, Factory +from attrs import Factory, define, field from griptape.artifacts import ListArtifact, TextArtifact from griptape.mixins.rule_mixin import RuleMixin diff --git a/griptape/tasks/base_task.py b/griptape/tasks/base_task.py index 9aa891e18..bf985a313 100644 --- a/griptape/tasks/base_task.py +++ b/griptape/tasks/base_task.py @@ -4,17 +4,17 @@ from abc import ABC, abstractmethod from concurrent import futures from enum import Enum -from typing import TYPE_CHECKING, Any, Optional, Callable +from typing import TYPE_CHECKING, Any, Callable, Optional -from attrs import define, field, Factory +from attrs import Factory, define, field -from griptape.events import StartTaskEvent, FinishTaskEvent from griptape.artifacts import ErrorArtifact +from griptape.events import FinishTaskEvent, StartTaskEvent if TYPE_CHECKING: from griptape.artifacts import BaseArtifact - from griptape.structures import Structure from griptape.memory.meta import BaseMetaEntry + from griptape.structures import Structure @define diff --git a/griptape/tasks/code_execution_task.py b/griptape/tasks/code_execution_task.py index 038642b76..68e0d66ad 100644 --- a/griptape/tasks/code_execution_task.py +++ b/griptape/tasks/code_execution_task.py @@ -1,8 +1,11 @@ from __future__ import annotations + +from typing import Callable + from attrs import define, field + from griptape.artifacts import BaseArtifact, ErrorArtifact from griptape.tasks import BaseTextInputTask -from typing import Callable @define diff --git a/griptape/tasks/csv_extraction_task.py b/griptape/tasks/csv_extraction_task.py index 8770187f0..538596dfe 100644 --- a/griptape/tasks/csv_extraction_task.py +++ b/griptape/tasks/csv_extraction_task.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define, field + from griptape.engines import CsvExtractionEngine from griptape.tasks import ExtractionTask diff --git a/griptape/tasks/extraction_task.py b/griptape/tasks/extraction_task.py index 8c9ac85b1..d8f492693 100644 --- a/griptape/tasks/extraction_task.py +++ b/griptape/tasks/extraction_task.py @@ -1,11 +1,14 @@ from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field + from griptape.tasks import BaseTextInputTask -from typing import TYPE_CHECKING if TYPE_CHECKING: + from griptape.artifacts import ErrorArtifact, ListArtifact from griptape.engines import BaseExtractionEngine - from griptape.artifacts import ListArtifact, ErrorArtifact @define diff --git a/griptape/tasks/inpainting_image_generation_task.py b/griptape/tasks/inpainting_image_generation_task.py index 838ab4489..5c508b534 100644 --- a/griptape/tasks/inpainting_image_generation_task.py +++ b/griptape/tasks/inpainting_image_generation_task.py @@ -4,8 +4,8 @@ from attrs import define, field +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact from griptape.engines import InpaintingImageGenerationEngine -from griptape.artifacts import ImageArtifact, TextArtifact, ListArtifact from griptape.tasks import BaseImageGenerationTask, BaseTask from griptape.utils import J2 diff --git a/griptape/tasks/json_extraction_task.py b/griptape/tasks/json_extraction_task.py index e1f082fd8..ce51b316f 100644 --- a/griptape/tasks/json_extraction_task.py +++ b/griptape/tasks/json_extraction_task.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define, field + from griptape.engines import JsonExtractionEngine from griptape.tasks import ExtractionTask diff --git a/griptape/tasks/outpainting_image_generation_task.py b/griptape/tasks/outpainting_image_generation_task.py index 135304ad3..8e7b210a2 100644 --- a/griptape/tasks/outpainting_image_generation_task.py +++ b/griptape/tasks/outpainting_image_generation_task.py @@ -4,8 +4,8 @@ from attrs import define, field +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact from griptape.engines import OutpaintingImageGenerationEngine -from griptape.artifacts import ImageArtifact, TextArtifact, ListArtifact from griptape.tasks import BaseImageGenerationTask, BaseTask from griptape.utils import J2 diff --git a/griptape/tasks/prompt_image_generation_task.py b/griptape/tasks/prompt_image_generation_task.py index 8c487d1ed..01bfd4b87 100644 --- a/griptape/tasks/prompt_image_generation_task.py +++ b/griptape/tasks/prompt_image_generation_task.py @@ -4,8 +4,8 @@ from attrs import define, field -from griptape.engines import PromptImageGenerationEngine from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.engines import PromptImageGenerationEngine from griptape.tasks import BaseImageGenerationTask, BaseTask from griptape.utils import J2 diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index c428e092d..adf140443 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -4,12 +4,11 @@ from attrs import Factory, define, field -from griptape.artifacts import BaseArtifact +from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact from griptape.common import PromptStack +from griptape.mixins import RuleMixin from griptape.tasks import BaseTask from griptape.utils import J2 -from griptape.artifacts import TextArtifact, ListArtifact -from griptape.mixins import RuleMixin if TYPE_CHECKING: from griptape.drivers import BasePromptDriver diff --git a/griptape/tasks/rag_task.py b/griptape/tasks/rag_task.py index fd5c5daa1..3f88f34d1 100644 --- a/griptape/tasks/rag_task.py +++ b/griptape/tasks/rag_task.py @@ -1,8 +1,11 @@ from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.artifacts import ErrorArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, ErrorArtifact from griptape.tasks import BaseTextInputTask -from typing import TYPE_CHECKING if TYPE_CHECKING: from griptape.engines.rag import RagEngine diff --git a/griptape/tasks/structure_run_task.py b/griptape/tasks/structure_run_task.py index 148b5b2de..887a33b8a 100644 --- a/griptape/tasks/structure_run_task.py +++ b/griptape/tasks/structure_run_task.py @@ -1,14 +1,14 @@ from __future__ import annotations +from typing import TYPE_CHECKING from attrs import define, field from griptape.tasks import BaseMultiTextInputTask -from typing import TYPE_CHECKING if TYPE_CHECKING: - from griptape.drivers.structure_run.base_structure_run_driver import BaseStructureRunDriver from griptape.artifacts import BaseArtifact + from griptape.drivers.structure_run.base_structure_run_driver import BaseStructureRunDriver @define diff --git a/griptape/tasks/text_summary_task.py b/griptape/tasks/text_summary_task.py index 648fb1cf1..5bd1b547e 100644 --- a/griptape/tasks/text_summary_task.py +++ b/griptape/tasks/text_summary_task.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import TYPE_CHECKING, Optional + from attrs import define, field + from griptape.artifacts import TextArtifact from griptape.engines import PromptSummaryEngine from griptape.tasks import BaseTextInputTask diff --git a/griptape/tasks/text_to_speech_task.py b/griptape/tasks/text_to_speech_task.py index 29a2f0165..ab01e298c 100644 --- a/griptape/tasks/text_to_speech_task.py +++ b/griptape/tasks/text_to_speech_task.py @@ -1,11 +1,11 @@ from __future__ import annotations -from typing import Callable, TYPE_CHECKING +from typing import TYPE_CHECKING, Callable from attrs import define, field -from griptape.engines import TextToSpeechEngine from griptape.artifacts import TextArtifact +from griptape.engines import TextToSpeechEngine from griptape.tasks.base_audio_generation_task import BaseAudioGenerationTask from griptape.utils import J2 diff --git a/griptape/tasks/tool_task.py b/griptape/tasks/tool_task.py index 447525f3e..ca548b34d 100644 --- a/griptape/tasks/tool_task.py +++ b/griptape/tasks/tool_task.py @@ -1,21 +1,24 @@ from __future__ import annotations + import json import re -from typing import Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, Optional + from attrs import define, field from griptape import utils -from griptape.artifacts import InfoArtifact, BaseArtifact, ErrorArtifact, ListArtifact -from griptape.tasks import PromptTask, ActionsSubtask -from griptape.utils import J2 +from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, ListArtifact from griptape.mixins import ActionsSubtaskOriginMixin +from griptape.tasks import ActionsSubtask, PromptTask +from griptape.utils import J2 if TYPE_CHECKING: from schema import Schema - from griptape.tools import BaseTool + from griptape.common import PromptStack from griptape.memory import TaskMemory from griptape.structures import Structure + from griptape.tools import BaseTool @define diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index 97835928c..6306fa7b3 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -1,21 +1,23 @@ from __future__ import annotations + import json from typing import TYPE_CHECKING, Callable, Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field from griptape import utils -from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact, ListArtifact, ActionArtifact +from griptape.artifacts import ActionArtifact, BaseArtifact, ErrorArtifact, ListArtifact, TextArtifact +from griptape.common import PromptStack, ToolAction from griptape.mixins import ActionsSubtaskOriginMixin -from griptape.tasks import ActionsSubtask -from griptape.tasks import PromptTask +from griptape.tasks import ActionsSubtask, PromptTask from griptape.utils import J2 -from griptape.common import PromptStack, ToolAction if TYPE_CHECKING: from schema import Schema - from griptape.tools import BaseTool + from griptape.memory import TaskMemory from griptape.structures import Structure + from griptape.tools import BaseTool @define diff --git a/griptape/tasks/variation_image_generation_task.py b/griptape/tasks/variation_image_generation_task.py index 1f2cebbfc..c3e71e0b5 100644 --- a/griptape/tasks/variation_image_generation_task.py +++ b/griptape/tasks/variation_image_generation_task.py @@ -4,8 +4,8 @@ from attrs import define, field +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact from griptape.engines import VariationImageGenerationEngine -from griptape.artifacts import ImageArtifact, TextArtifact, ListArtifact from griptape.tasks import BaseImageGenerationTask, BaseTask from griptape.utils import J2 diff --git a/griptape/tokenizers/amazon_bedrock_tokenizer.py b/griptape/tokenizers/amazon_bedrock_tokenizer.py index 951802d59..292dcde17 100644 --- a/griptape/tokenizers/amazon_bedrock_tokenizer.py +++ b/griptape/tokenizers/amazon_bedrock_tokenizer.py @@ -1,6 +1,7 @@ from __future__ import annotations from attrs import define, field + from griptape.tokenizers.base_tokenizer import BaseTokenizer diff --git a/griptape/tokenizers/anthropic_tokenizer.py b/griptape/tokenizers/anthropic_tokenizer.py index f5fabab0e..0955a506b 100644 --- a/griptape/tokenizers/anthropic_tokenizer.py +++ b/griptape/tokenizers/anthropic_tokenizer.py @@ -1,8 +1,11 @@ from __future__ import annotations -from attrs import define, field, Factory + from typing import TYPE_CHECKING -from griptape.utils import import_optional_dependency + +from attrs import Factory, define, field + from griptape.tokenizers import BaseTokenizer +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from anthropic import Anthropic diff --git a/griptape/tokenizers/base_tokenizer.py b/griptape/tokenizers/base_tokenizer.py index 212e40058..5b334f096 100644 --- a/griptape/tokenizers/base_tokenizer.py +++ b/griptape/tokenizers/base_tokenizer.py @@ -1,7 +1,9 @@ from __future__ import annotations + import logging from abc import ABC, abstractmethod -from attrs import define, field, Factory + +from attrs import Factory, define, field @define() diff --git a/griptape/tokenizers/cohere_tokenizer.py b/griptape/tokenizers/cohere_tokenizer.py index ae3bddd80..a0abf55c7 100644 --- a/griptape/tokenizers/cohere_tokenizer.py +++ b/griptape/tokenizers/cohere_tokenizer.py @@ -1,6 +1,9 @@ from __future__ import annotations + from typing import TYPE_CHECKING + from attrs import define, field + from griptape.tokenizers import BaseTokenizer if TYPE_CHECKING: diff --git a/griptape/tokenizers/dummy_tokenizer.py b/griptape/tokenizers/dummy_tokenizer.py index a36d0343e..b13b1fecb 100644 --- a/griptape/tokenizers/dummy_tokenizer.py +++ b/griptape/tokenizers/dummy_tokenizer.py @@ -1,6 +1,9 @@ from __future__ import annotations -from attrs import define, field + from typing import Optional + +from attrs import define, field + from griptape.exceptions import DummyException from griptape.tokenizers import BaseTokenizer diff --git a/griptape/tokenizers/google_tokenizer.py b/griptape/tokenizers/google_tokenizer.py index f99a0682f..45e927cc9 100644 --- a/griptape/tokenizers/google_tokenizer.py +++ b/griptape/tokenizers/google_tokenizer.py @@ -1,8 +1,11 @@ from __future__ import annotations -from attrs import define, field, Factory + from typing import TYPE_CHECKING -from griptape.utils import import_optional_dependency + +from attrs import Factory, define, field + from griptape.tokenizers import BaseTokenizer +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from google.generativeai import GenerativeModel diff --git a/griptape/tokenizers/huggingface_tokenizer.py b/griptape/tokenizers/huggingface_tokenizer.py index fdebd23da..63ddf0ea7 100644 --- a/griptape/tokenizers/huggingface_tokenizer.py +++ b/griptape/tokenizers/huggingface_tokenizer.py @@ -1,9 +1,11 @@ from __future__ import annotations from typing import TYPE_CHECKING -from attrs import define, field, Factory -from griptape.utils import import_optional_dependency + +from attrs import Factory, define, field + from griptape.tokenizers import BaseTokenizer +from griptape.utils import import_optional_dependency if TYPE_CHECKING: from transformers import PreTrainedTokenizerBase diff --git a/griptape/tokenizers/simple_tokenizer.py b/griptape/tokenizers/simple_tokenizer.py index b4e125680..214e5be2d 100644 --- a/griptape/tokenizers/simple_tokenizer.py +++ b/griptape/tokenizers/simple_tokenizer.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define, field + from griptape.tokenizers import BaseTokenizer diff --git a/griptape/tools/audio_transcription_client/tool.py b/griptape/tools/audio_transcription_client/tool.py index 3fdde0102..786fb406b 100644 --- a/griptape/tools/audio_transcription_client/tool.py +++ b/griptape/tools/audio_transcription_client/tool.py @@ -1,11 +1,11 @@ from __future__ import annotations -from typing import Any, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, cast -from attrs import define, field, Factory -from schema import Schema, Literal +from attrs import Factory, define, field +from schema import Literal, Schema -from griptape.artifacts import ErrorArtifact, AudioArtifact, TextArtifact +from griptape.artifacts import AudioArtifact, ErrorArtifact, TextArtifact from griptape.loaders.audio_loader import AudioLoader from griptape.tools import BaseTool from griptape.utils import load_artifact_from_memory diff --git a/griptape/tools/aws_iam_client/tool.py b/griptape/tools/aws_iam_client/tool.py index 467540829..b9f149b23 100644 --- a/griptape/tools/aws_iam_client/tool.py +++ b/griptape/tools/aws_iam_client/tool.py @@ -1,10 +1,13 @@ from __future__ import annotations + from typing import TYPE_CHECKING -from schema import Schema, Literal -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact, ErrorArtifact, ListArtifact -from griptape.utils.decorators import activity + +from attrs import Factory, define, field +from schema import Literal, Schema + +from griptape.artifacts import ErrorArtifact, ListArtifact, TextArtifact from griptape.tools import BaseAwsClient +from griptape.utils.decorators import activity if TYPE_CHECKING: from mypy_boto3_iam import Client diff --git a/griptape/tools/aws_s3_client/tool.py b/griptape/tools/aws_s3_client/tool.py index 9d50c7cf8..e69db8390 100644 --- a/griptape/tools/aws_s3_client/tool.py +++ b/griptape/tools/aws_s3_client/tool.py @@ -1,11 +1,14 @@ from __future__ import annotations + import io -from typing import Any, TYPE_CHECKING -from schema import Schema, Literal -from attrs import define, field, Factory -from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact, ListArtifact, BlobArtifact -from griptape.utils.decorators import activity +from typing import TYPE_CHECKING, Any + +from attrs import Factory, define, field +from schema import Literal, Schema + +from griptape.artifacts import BlobArtifact, ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.tools import BaseAwsClient +from griptape.utils.decorators import activity if TYPE_CHECKING: from mypy_boto3_s3 import Client diff --git a/griptape/tools/base_aws_client.py b/griptape/tools/base_aws_client.py index bd7b41e59..8c6d02e2b 100644 --- a/griptape/tools/base_aws_client.py +++ b/griptape/tools/base_aws_client.py @@ -1,8 +1,11 @@ from __future__ import annotations -from typing import TYPE_CHECKING + from abc import ABC +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.artifacts import TextArtifact, ErrorArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity diff --git a/griptape/tools/base_google_client.py b/griptape/tools/base_google_client.py index 51ae2f946..4a15770ec 100644 --- a/griptape/tools/base_google_client.py +++ b/griptape/tools/base_google_client.py @@ -1,7 +1,9 @@ from abc import ABC +from typing import Any, Optional + from attrs import define, field + from griptape.tools import BaseTool -from typing import Optional, Any @define diff --git a/griptape/tools/base_griptape_cloud_client.py b/griptape/tools/base_griptape_cloud_client.py index 3e7f44fe6..908f59b52 100644 --- a/griptape/tools/base_griptape_cloud_client.py +++ b/griptape/tools/base_griptape_cloud_client.py @@ -1,6 +1,9 @@ from __future__ import annotations + from abc import ABC + from attrs import Factory, define, field + from griptape.tools import BaseTool diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index bfff2fffb..1e71e6a8f 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -1,16 +1,18 @@ from __future__ import annotations + +import inspect import logging +import os import subprocess import sys -from typing import TYPE_CHECKING, Callable -from schema import Schema, Literal, Or -import inspect -import os from abc import ABC -from typing import Optional +from typing import TYPE_CHECKING, Callable, Optional + import yaml -from attrs import define, field, Factory -from griptape.artifacts import BaseArtifact, InfoArtifact, TextArtifact, ErrorArtifact +from attrs import Factory, define, field +from schema import Literal, Or, Schema + +from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, TextArtifact from griptape.mixins import ActivityMixin if TYPE_CHECKING: diff --git a/griptape/tools/calculator/tool.py b/griptape/tools/calculator/tool.py index 141da0bfc..02e5fe95e 100644 --- a/griptape/tools/calculator/tool.py +++ b/griptape/tools/calculator/tool.py @@ -1,7 +1,8 @@ +from schema import Literal, Schema + from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity -from schema import Schema, Literal class Calculator(BaseTool): diff --git a/griptape/tools/computer/tool.py b/griptape/tools/computer/tool.py index b63ba9e0b..565389a3f 100644 --- a/griptape/tools/computer/tool.py +++ b/griptape/tools/computer/tool.py @@ -1,21 +1,23 @@ from __future__ import annotations + import logging import os import shutil import tempfile from pathlib import Path -from typing import Optional, TYPE_CHECKING -from attrs import define, field, Factory -from docker.models.containers import Container -from schema import Schema, Literal -import stringcase +from typing import TYPE_CHECKING, Optional + import docker +import stringcase +from attrs import Factory, define, field from docker.errors import NotFound +from docker.models.containers import Container +from schema import Literal, Schema + from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity - if TYPE_CHECKING: from docker import DockerClient diff --git a/griptape/tools/date_time/tool.py b/griptape/tools/date_time/tool.py index c72ff4f8c..886969575 100644 --- a/griptape/tools/date_time/tool.py +++ b/griptape/tools/date_time/tool.py @@ -1,5 +1,7 @@ from datetime import datetime -from schema import Schema, Literal + +from schema import Literal, Schema + from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity diff --git a/griptape/tools/email_client/tool.py b/griptape/tools/email_client/tool.py index 6e0b32dc3..622c21fa3 100644 --- a/griptape/tools/email_client/tool.py +++ b/griptape/tools/email_client/tool.py @@ -1,15 +1,18 @@ from __future__ import annotations -from attrs import Factory, define, field + +import logging +import smtplib from email.mime.text import MIMEText +from typing import Optional + +import schema +from attrs import Factory, define, field +from schema import Literal, Schema + from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact from griptape.loaders.email_loader import EmailLoader from griptape.tools import BaseTool from griptape.utils.decorators import activity -from schema import Schema, Literal -from typing import Optional -import logging -import schema -import smtplib @define diff --git a/griptape/tools/file_manager/tool.py b/griptape/tools/file_manager/tool.py index 47582f8cc..db6ef451a 100644 --- a/griptape/tools/file_manager/tool.py +++ b/griptape/tools/file_manager/tool.py @@ -1,11 +1,14 @@ from __future__ import annotations + import os -from attrs import define, field, Factory + +from attrs import Factory, define, field +from schema import Literal, Schema + from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.drivers import BaseFileManagerDriver, LocalFileManagerDriver from griptape.tools import BaseTool from griptape.utils.decorators import activity -from schema import Schema, Literal @define diff --git a/griptape/tools/google_cal/tool.py b/griptape/tools/google_cal/tool.py index e0097fd02..85f6158cd 100644 --- a/griptape/tools/google_cal/tool.py +++ b/griptape/tools/google_cal/tool.py @@ -1,11 +1,14 @@ from __future__ import annotations -import logging + import datetime -from schema import Schema, Literal, Optional +import logging + from attrs import define, field -from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact, ListArtifact -from griptape.utils.decorators import activity +from schema import Literal, Optional, Schema + +from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.tools import BaseGoogleClient +from griptape.utils.decorators import activity @define diff --git a/griptape/tools/google_docs/tool.py b/griptape/tools/google_docs/tool.py index 48dbbe39c..2cab05208 100644 --- a/griptape/tools/google_docs/tool.py +++ b/griptape/tools/google_docs/tool.py @@ -1,12 +1,13 @@ from __future__ import annotations + import logging -from attrs import field, define -from schema import Schema, Optional, Literal -from griptape.artifacts import ErrorArtifact, InfoArtifact +from attrs import define, field +from schema import Literal, Optional, Schema -from griptape.utils.decorators import activity +from griptape.artifacts import ErrorArtifact, InfoArtifact from griptape.tools import BaseGoogleClient +from griptape.utils.decorators import activity @define diff --git a/griptape/tools/google_drive/tool.py b/griptape/tools/google_drive/tool.py index fcb042cfb..427ed5e0a 100644 --- a/griptape/tools/google_drive/tool.py +++ b/griptape/tools/google_drive/tool.py @@ -1,13 +1,16 @@ from __future__ import annotations + import logging +from io import BytesIO from typing import Any, Optional + import schema -from schema import Schema, Literal, Or from attrs import define, field -from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact, BlobArtifact, TextArtifact -from griptape.utils.decorators import activity +from schema import Literal, Or, Schema + +from griptape.artifacts import BlobArtifact, ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.tools import BaseGoogleClient -from io import BytesIO +from griptape.utils.decorators import activity @define diff --git a/griptape/tools/google_gmail/tool.py b/griptape/tools/google_gmail/tool.py index 5b4bf5cd5..137f2584b 100644 --- a/griptape/tools/google_gmail/tool.py +++ b/griptape/tools/google_gmail/tool.py @@ -1,12 +1,15 @@ from __future__ import annotations -import logging + import base64 +import logging from email.message import EmailMessage -from schema import Schema, Literal + from attrs import define, field -from griptape.artifacts import InfoArtifact, ErrorArtifact -from griptape.utils.decorators import activity +from schema import Literal, Schema + +from griptape.artifacts import ErrorArtifact, InfoArtifact from griptape.tools import BaseGoogleClient +from griptape.utils.decorators import activity @define diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 281c13b60..438d09aa0 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -1,11 +1,14 @@ from __future__ import annotations + from typing import Optional from urllib.parse import urljoin -from schema import Schema, Literal + from attrs import define, field +from schema import Literal, Schema + +from griptape.artifacts import ErrorArtifact, TextArtifact from griptape.tools.base_griptape_cloud_client import BaseGriptapeCloudClient from griptape.utils.decorators import activity -from griptape.artifacts import TextArtifact, ErrorArtifact @define @@ -29,7 +32,7 @@ class GriptapeCloudKnowledgeBaseClient(BaseGriptapeCloudClient): } ) def query(self, params: dict) -> TextArtifact | ErrorArtifact: - from requests import post, exceptions + from requests import exceptions, post query = params["values"]["query"] url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/search") diff --git a/griptape/tools/image_query_client/tool.py b/griptape/tools/image_query_client/tool.py index b03f3fed0..aeaa3e4b2 100644 --- a/griptape/tools/image_query_client/tool.py +++ b/griptape/tools/image_query_client/tool.py @@ -1,11 +1,11 @@ from __future__ import annotations -from typing import Any, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, cast -from attrs import define, field, Factory -from schema import Schema, Literal +from attrs import Factory, define, field +from schema import Literal, Schema -from griptape.artifacts import TextArtifact, ImageArtifact, ErrorArtifact, BlobArtifact +from griptape.artifacts import BlobArtifact, ErrorArtifact, ImageArtifact, TextArtifact from griptape.loaders import ImageLoader from griptape.tools import BaseTool from griptape.utils import load_artifact_from_memory diff --git a/griptape/tools/inpainting_image_generation_client/tool.py b/griptape/tools/inpainting_image_generation_client/tool.py index c343f9923..7c57e6f08 100644 --- a/griptape/tools/inpainting_image_generation_client/tool.py +++ b/griptape/tools/inpainting_image_generation_client/tool.py @@ -1,9 +1,9 @@ from __future__ import annotations -from typing import Any, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, cast from attrs import define, field -from schema import Schema, Literal +from schema import Literal, Schema from griptape.artifacts import ErrorArtifact, ImageArtifact from griptape.loaders import ImageLoader diff --git a/griptape/tools/openweather_client/tool.py b/griptape/tools/openweather_client/tool.py index e338677dd..21b80c6f0 100644 --- a/griptape/tools/openweather_client/tool.py +++ b/griptape/tools/openweather_client/tool.py @@ -1,12 +1,15 @@ from __future__ import annotations -from griptape.artifacts import ListArtifact, TextArtifact, ErrorArtifact, InfoArtifact -from griptape.tools import BaseTool -from griptape.utils.decorators import activity -from schema import Schema, Literal + +import logging from typing import Optional -from attrs import define, field + import requests -import logging +from attrs import define, field +from schema import Literal, Schema + +from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact +from griptape.tools import BaseTool +from griptape.utils.decorators import activity @define diff --git a/griptape/tools/outpainting_image_generation_client/tool.py b/griptape/tools/outpainting_image_generation_client/tool.py index 72db0e54c..0e355b1dc 100644 --- a/griptape/tools/outpainting_image_generation_client/tool.py +++ b/griptape/tools/outpainting_image_generation_client/tool.py @@ -1,15 +1,15 @@ from __future__ import annotations -from typing import Any, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, cast from attrs import define, field -from schema import Schema, Literal +from schema import Literal, Schema from griptape.artifacts import ErrorArtifact, ImageArtifact from griptape.loaders import ImageLoader +from griptape.mixins import BlobArtifactFileOutputMixin from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.mixins import BlobArtifactFileOutputMixin from griptape.utils.load_artifact_from_memory import load_artifact_from_memory if TYPE_CHECKING: diff --git a/griptape/tools/prompt_image_generation_client/tool.py b/griptape/tools/prompt_image_generation_client/tool.py index 799df8673..17e2f6768 100644 --- a/griptape/tools/prompt_image_generation_client/tool.py +++ b/griptape/tools/prompt_image_generation_client/tool.py @@ -1,16 +1,17 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from attrs import define, field -from schema import Schema, Literal +from schema import Literal, Schema +from griptape.mixins import BlobArtifactFileOutputMixin from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.mixins import BlobArtifactFileOutputMixin -from typing import TYPE_CHECKING if TYPE_CHECKING: - from griptape.engines import PromptImageGenerationEngine from griptape.artifacts import ErrorArtifact, ImageArtifact + from griptape.engines import PromptImageGenerationEngine @define diff --git a/griptape/tools/rag_client/tool.py b/griptape/tools/rag_client/tool.py index 36ab82bf3..afc1b9d06 100644 --- a/griptape/tools/rag_client/tool.py +++ b/griptape/tools/rag_client/tool.py @@ -1,10 +1,13 @@ from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from schema import Schema, Literal -from griptape.artifacts import ErrorArtifact, BaseArtifact +from schema import Literal, Schema + +from griptape.artifacts import BaseArtifact, ErrorArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity -from typing import TYPE_CHECKING if TYPE_CHECKING: from griptape.engines.rag import RagEngine diff --git a/griptape/tools/rest_api_client/tool.py b/griptape/tools/rest_api_client/tool.py index 6206c1dba..fd63ab500 100644 --- a/griptape/tools/rest_api_client/tool.py +++ b/griptape/tools/rest_api_client/tool.py @@ -1,12 +1,14 @@ from textwrap import dedent from typing import Optional from urllib.parse import urljoin + import schema -from schema import Schema, Literal from attrs import define, field +from schema import Literal, Schema + +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.artifacts import BaseArtifact, TextArtifact, ErrorArtifact @define @@ -51,7 +53,7 @@ def full_url(self) -> str: } ) def put(self, params: dict) -> BaseArtifact: - from requests import put, exceptions + from requests import exceptions, put values = params["values"] base_url = self.base_url @@ -86,7 +88,7 @@ def put(self, params: dict) -> BaseArtifact: } ) def patch(self, params: dict) -> BaseArtifact: - from requests import patch, exceptions + from requests import exceptions, patch values = params["values"] base_url = self.base_url @@ -115,7 +117,7 @@ def patch(self, params: dict) -> BaseArtifact: } ) def post(self, params: dict) -> BaseArtifact: - from requests import post, exceptions + from requests import exceptions, post values = params["values"] base_url = self.base_url @@ -151,7 +153,7 @@ def post(self, params: dict) -> BaseArtifact: } ) def get(self, params: dict) -> BaseArtifact: - from requests import get, exceptions + from requests import exceptions, get values = params["values"] base_url = self.base_url diff --git a/griptape/tools/sql_client/tool.py b/griptape/tools/sql_client/tool.py index c06cfe4d9..93c69c51b 100644 --- a/griptape/tools/sql_client/tool.py +++ b/griptape/tools/sql_client/tool.py @@ -1,10 +1,13 @@ from __future__ import annotations -from typing import Optional, TYPE_CHECKING + +from typing import TYPE_CHECKING, Optional + from attrs import define, field -from griptape.artifacts import InfoArtifact, ListArtifact, ErrorArtifact +from schema import Schema + +from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity -from schema import Schema if TYPE_CHECKING: from griptape.loaders import SqlLoader diff --git a/griptape/tools/structure_run_client/tool.py b/griptape/tools/structure_run_client/tool.py index 79ed635df..0a1cc223b 100644 --- a/griptape/tools/structure_run_client/tool.py +++ b/griptape/tools/structure_run_client/tool.py @@ -1,12 +1,13 @@ from __future__ import annotations +from typing import TYPE_CHECKING + from attrs import define, field from schema import Literal, Schema from griptape.artifacts import BaseArtifact, TextArtifact from griptape.tools.base_tool import BaseTool from griptape.utils.decorators import activity -from typing import TYPE_CHECKING if TYPE_CHECKING: from griptape.drivers import BaseStructureRunDriver diff --git a/griptape/tools/task_memory_client/tool.py b/griptape/tools/task_memory_client/tool.py index ce89da22e..406f50fed 100644 --- a/griptape/tools/task_memory_client/tool.py +++ b/griptape/tools/task_memory_client/tool.py @@ -1,7 +1,9 @@ from __future__ import annotations + from attrs import define -from schema import Schema, Literal -from griptape.artifacts import TextArtifact, ErrorArtifact, InfoArtifact, BaseArtifact +from schema import Literal, Schema + +from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, TextArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity diff --git a/griptape/tools/text_to_speech_client/tool.py b/griptape/tools/text_to_speech_client/tool.py index 675320d83..9649279be 100644 --- a/griptape/tools/text_to_speech_client/tool.py +++ b/griptape/tools/text_to_speech_client/tool.py @@ -1,17 +1,17 @@ from __future__ import annotations -from typing import Any, TYPE_CHECKING +from typing import TYPE_CHECKING, Any from attrs import define, field -from schema import Schema, Literal +from schema import Literal, Schema +from griptape.mixins import BlobArtifactFileOutputMixin from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.mixins import BlobArtifactFileOutputMixin if TYPE_CHECKING: + from griptape.artifacts import AudioArtifact, ErrorArtifact from griptape.engines import TextToSpeechEngine - from griptape.artifacts import ErrorArtifact, AudioArtifact @define diff --git a/griptape/tools/variation_image_generation_client/tool.py b/griptape/tools/variation_image_generation_client/tool.py index 40afab05a..c1ab91896 100644 --- a/griptape/tools/variation_image_generation_client/tool.py +++ b/griptape/tools/variation_image_generation_client/tool.py @@ -1,15 +1,15 @@ from __future__ import annotations -from typing import Any, cast, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, cast from attrs import define, field -from schema import Schema, Literal +from schema import Literal, Schema from griptape.artifacts import ErrorArtifact, ImageArtifact from griptape.loaders import ImageLoader +from griptape.mixins import BlobArtifactFileOutputMixin from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.mixins import BlobArtifactFileOutputMixin from griptape.utils.load_artifact_from_memory import load_artifact_from_memory if TYPE_CHECKING: diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index 8a334c21a..ef831e508 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -1,9 +1,11 @@ from __future__ import annotations -from typing import Callable, Any, TYPE_CHECKING -from attrs import define, field, Factory -from schema import Schema, Literal -from griptape.artifacts import ErrorArtifact, BaseArtifact -from griptape.artifacts import ListArtifact + +from typing import TYPE_CHECKING, Any, Callable + +from attrs import Factory, define, field +from schema import Literal, Schema + +from griptape.artifacts import BaseArtifact, ErrorArtifact, ListArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity diff --git a/griptape/tools/web_scraper/tool.py b/griptape/tools/web_scraper/tool.py index c42dedad9..a72378bb2 100644 --- a/griptape/tools/web_scraper/tool.py +++ b/griptape/tools/web_scraper/tool.py @@ -1,10 +1,12 @@ from __future__ import annotations -from attrs import define, field, Factory + +from attrs import Factory, define, field +from schema import Literal, Schema + from griptape.artifacts import ErrorArtifact, ListArtifact -from schema import Schema, Literal +from griptape.loaders import WebLoader from griptape.tools import BaseTool from griptape.utils.decorators import activity -from griptape.loaders import WebLoader @define diff --git a/griptape/tools/web_search/tool.py b/griptape/tools/web_search/tool.py index 17c62dcc4..5a3360077 100644 --- a/griptape/tools/web_search/tool.py +++ b/griptape/tools/web_search/tool.py @@ -1,10 +1,13 @@ from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field +from schema import Literal, Schema + from griptape.artifacts import ErrorArtifact, ListArtifact -from schema import Schema, Literal from griptape.tools import BaseTool from griptape.utils.decorators import activity -from typing import TYPE_CHECKING if TYPE_CHECKING: from griptape.drivers import BaseWebSearchDriver diff --git a/griptape/utils/command_runner.py b/griptape/utils/command_runner.py index bbc03ec39..957be8272 100644 --- a/griptape/utils/command_runner.py +++ b/griptape/utils/command_runner.py @@ -1,6 +1,8 @@ import subprocess + from attrs import define -from griptape.artifacts import BaseArtifact, TextArtifact, ErrorArtifact + +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact @define diff --git a/griptape/utils/conversation.py b/griptape/utils/conversation.py index ae05e8b99..25dd310e1 100644 --- a/griptape/utils/conversation.py +++ b/griptape/utils/conversation.py @@ -1,5 +1,7 @@ from __future__ import annotations + from typing import TYPE_CHECKING + from attrs import define, field if TYPE_CHECKING: diff --git a/griptape/utils/decorators.py b/griptape/utils/decorators.py index d2c2a4951..83811d9a6 100644 --- a/griptape/utils/decorators.py +++ b/griptape/utils/decorators.py @@ -1,8 +1,8 @@ import functools + import schema from schema import Schema - CONFIG_SCHEMA = Schema({"description": str, schema.Optional("schema"): Schema}) diff --git a/griptape/utils/file_utils.py b/griptape/utils/file_utils.py index daf2982d8..ecefcc6b6 100644 --- a/griptape/utils/file_utils.py +++ b/griptape/utils/file_utils.py @@ -1,7 +1,8 @@ -import griptape.utils as utils from concurrent import futures from typing import Optional +import griptape.utils as utils + def load_file(path: str) -> bytes: """Load a file from the given path and return its content as bytes. diff --git a/griptape/utils/import_utils.py b/griptape/utils/import_utils.py index b3e830caf..9ad25be20 100644 --- a/griptape/utils/import_utils.py +++ b/griptape/utils/import_utils.py @@ -2,7 +2,6 @@ from types import ModuleType from typing import Optional - INSTALL_MAPPING = { "huggingface_hub": "huggingface-hub", "pinecone": "pinecone-client", diff --git a/griptape/utils/j2.py b/griptape/utils/j2.py index ca54fed9e..52d7eb69e 100644 --- a/griptape/utils/j2.py +++ b/griptape/utils/j2.py @@ -1,6 +1,8 @@ from typing import Optional -from attrs import define, field, Factory + +from attrs import Factory, define, field from jinja2 import Environment, FileSystemLoader + from .paths import abs_path diff --git a/griptape/utils/python_runner.py b/griptape/utils/python_runner.py index 75b6e53c2..009d17b7f 100644 --- a/griptape/utils/python_runner.py +++ b/griptape/utils/python_runner.py @@ -1,6 +1,7 @@ import importlib import sys from io import StringIO + from attrs import define, field diff --git a/griptape/utils/stream.py b/griptape/utils/stream.py index 18df1ba56..32e31ea7b 100644 --- a/griptape/utils/stream.py +++ b/griptape/utils/stream.py @@ -1,16 +1,20 @@ from __future__ import annotations -from typing import TYPE_CHECKING -from threading import Thread + from queue import Queue +from threading import Thread +from typing import TYPE_CHECKING + +from attrs import Factory, define, field + from griptape.artifacts.text_artifact import TextArtifact from griptape.events.completion_chunk_event import CompletionChunkEvent from griptape.events.event_listener import EventListener -from griptape.events.finish_structure_run_event import FinishStructureRunEvent from griptape.events.finish_prompt_event import FinishPromptEvent -from attrs import field, define, Factory +from griptape.events.finish_structure_run_event import FinishStructureRunEvent if TYPE_CHECKING: from collections.abc import Iterator + from griptape.events.base_event import BaseEvent from griptape.structures import Structure diff --git a/griptape/utils/structure_visualizer.py b/griptape/utils/structure_visualizer.py index 7c315a0bc..f24443cd6 100644 --- a/griptape/utils/structure_visualizer.py +++ b/griptape/utils/structure_visualizer.py @@ -1,13 +1,14 @@ from __future__ import annotations + import base64 import hashlib +from typing import TYPE_CHECKING from attrs import define, field -from typing import TYPE_CHECKING if TYPE_CHECKING: - from griptape.tasks import BaseTask from griptape.structures import Structure + from griptape.tasks import BaseTask @define diff --git a/pyproject.toml b/pyproject.toml index 49e786a1d..6e0b43917 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -211,7 +211,8 @@ select = [ "T201", # print "C901", # complex-structure "TCH", # flake8-type-checking - "D" # pydocstyle + "D", # pydocstyle + "I" # isort ] ignore = [ "UP007", # non-pep604-annotation @@ -231,6 +232,9 @@ ignore = [ [tool.ruff.lint.pydocstyle] convention = "google" +[tool.ruff.lint.per-file-ignores] +"__init__.py" = ["I"] + [tool.ruff.lint.flake8-tidy-imports.banned-api] "attr".msg = "The attr module is deprecated, use attrs instead." From 9fb4dd925cc677c3b2fa57b249e6f23f5a6aa6f2 Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Fri, 12 Jul 2024 13:05:58 -0700 Subject: [PATCH 61/87] GriptapeCloudVectorStoreDriver (#885) --- CHANGELOG.md | 1 + .../drivers/vector-store-drivers.md | 189 +++++++++++------- griptape/drivers/__init__.py | 2 + ...loud_knowledge_base_vector_store_driver.py | 101 ++++++++++ ...loud_knowledge_base_vector_store_driver.py | 69 +++++++ 5 files changed, 294 insertions(+), 68 deletions(-) create mode 100644 griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py create mode 100644 tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 82eaeef3c..cd83a793c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Native function calling support to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AnthropicPromptDriver`, `AmazonBedrockPromptDriver`, `GooglePromptDriver`, and `CoherePromptDriver`. - `OllamaEmbeddingDriver` for generating embeddings with Ollama. +- `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. ### Changed diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index da6fdc242..ea2b72a56 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -1,6 +1,6 @@ ## Overview -Griptape provides a way to build drivers for vector DBs where embeddings can be stored and queried. Every vector store driver implements the following methods: +Griptape provides a way to build drivers for vector DBs where embeddings can be stored and queried. Every Vector Store Driver implements the following methods: - `upsert_text_artifact()` for updating or inserting a new [TextArtifact](../../reference/griptape/artifacts/text_artifact.md) into vector DBs. The method will automatically generate embeddings for a given value. - `upsert_text_artifacts()` for updating or inserting multiple [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s into vector DBs. The method will automatically generate embeddings for given values. @@ -8,19 +8,19 @@ Griptape provides a way to build drivers for vector DBs where embeddings can be - `upsert_vector()` for updating and inserting new vectors directly. - `query()` for querying vector DBs. -Each vector driver takes a [BaseEmbeddingDriver](../../reference/griptape/drivers/embedding/base_embedding_driver.md) used to dynamically generate embeddings for strings. +Each Vector Store Driver takes a [BaseEmbeddingDriver](../../reference/griptape/drivers/embedding/base_embedding_driver.md) used to dynamically generate embeddings for strings. !!! info - When working with vector database indexes with Griptape drivers, make sure the number of dimensions is equal to 1536. Nearly all embedding models create vectors with this number of dimensions. Check the documentation for your vector database on how to create/update vector indexes. + When working with vector database indexes with Griptape Drivers, make sure the number of dimensions is equal to 1536. Nearly all embedding models create vectors with this number of dimensions. Check the documentation for your vector database on how to create/update vector indexes. !!! info - More vector drivers are coming soon. + More Vector Store Drivers are coming soon. ## Vector Store Drivers ### Local -The [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) can be used to load and query data from memory. Here is a complete example of how the driver can be used to load a webpage into the driver and query it later: +The [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vector_store_driver.md) can be used to load and query data from memory. Here is a complete example of how the Driver can be used to load a webpage into the Driver and query it later: ```python import os @@ -29,12 +29,15 @@ from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader -# Initialize an embedding driver +# Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) vector_store_driver = LocalVectorStoreDriver(embedding_driver=embedding_driver) + +# Load Artifacts from the web artifacts = WebLoader(max_tokens=100).load("https://www.griptape.ai") +# Upsert Artifacts into the Vector Store Driver [vector_store_driver.upsert_text_artifact(a, namespace="griptape") for a in artifacts] results = vector_store_driver.query( @@ -49,14 +52,38 @@ print("\n\n".join(values)) ``` +### Griptape Cloud Knowledge Base + +The [GriptapeCloudKnowledgeBaseVectorStoreDriver](../../reference/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.md) can be used to query data from a Griptape Cloud Knowledge Base. Loading into Knowledge Bases is not supported at this time, only querying. Here is a complete example of how the Driver can be used to query an existing Knowledge Base: + +```python +import os +from griptape.artifacts import BaseArtifact +from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver + + +# Initialize environment variables +gt_cloud_api_key = os.environ["GRIPTAPE_CLOUD_API_KEY"] +gt_cloud_knowledge_base_id = os.environ["GRIPTAPE_CLOUD_KB_ID"] + +vector_store_driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key=gt_cloud_api_key, knowledge_base_id=gt_cloud_knowledge_base_id) + +results =vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) + +``` + ### Pinecone !!! info - This driver requires the `drivers-vector-pinecone` [extra](../index.md#extras). + This Driver requires the `drivers-vector-pinecone` [extra](../index.md#extras). The [PineconeVectorStoreDriver](../../reference/griptape/drivers/vector/pinecone_vector_store_driver.md) supports the [Pinecone vector database](https://www.pinecone.io/). -Here is an example of how the driver can be used to load and query information in a Pinecone cluster: +Here is an example of how the Driver can be used to load and query information in a Pinecone cluster: ```python import os @@ -85,7 +112,7 @@ def load_data(driver: PineconeVectorStoreDriver) -> None: namespace="supermarket-products", ) -# Initialize an embedding driver +# Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) vector_store_driver = PineconeVectorStoreDriver( @@ -97,72 +124,79 @@ vector_store_driver = PineconeVectorStoreDriver( load_data(vector_store_driver) -result = vector_store_driver.query( +results = vector_store_driver.query( "fruit", count=3, filter={"price": {"$lte": 15}, "rating": {"$gte": 4}}, namespace="supermarket-products", ) + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` ### Marqo !!! info - This driver requires the `drivers-vector-marqo` [extra](../index.md#extras). + This Driver requires the `drivers-vector-marqo` [extra](../index.md#extras). The [MarqoVectorStoreDriver](../../reference/griptape/drivers/vector/marqo_vector_store_driver.md) supports the Marqo vector database. -Here is an example of how the driver can be used to load and query information in a Marqo cluster: +Here is an example of how the Driver can be used to load and query information in a Marqo cluster: ```python import os from griptape.drivers import MarqoVectorStoreDriver, OpenAiEmbeddingDriver, OpenAiChatPromptDriver from griptape.loaders import WebLoader -# Initialize an embedding driver +# Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) prompt_driver = OpenAiChatPromptDriver(model="gpt-3.5-turbo") # Define the namespace namespace = 'griptape-ai' -# Initialize the vector store driver -vector_store = MarqoVectorStoreDriver( +# Initialize the Vector Store Driver +vector_store_driver = MarqoVectorStoreDriver( api_key=os.environ["MARQO_API_KEY"], url=os.environ["MARQO_URL"], index=os.environ["MARQO_INDEX_NAME"], embedding_driver=embedding_driver, ) -# Load artifacts from the web +# Load Artifacts from the web artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") -# Upsert the artifacts into the vector store -vector_store.upsert_text_artifacts( +# Upsert Artifacts into the Vector Store Driver +vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store.query(query="What is griptape?") -print(result) +results =vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` ### Mongodb Atlas !!! info - This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). + This Driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). The [MongodbAtlasVectorStoreDriver](../../reference/griptape/drivers/vector/mongodb_atlas_vector_store_driver.md) provides support for storing vector data in a MongoDB Atlas database. -Here is an example of how the driver can be used to load and query information in a MongoDb Atlas Cluster: +Here is an example of how the Driver can be used to load and query information in a MongoDb Atlas Cluster: ```python from griptape.drivers import MongoDbAtlasVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader import os -# Initialize an embedding driver +# Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) host = os.environ["MONGODB_HOST"] @@ -173,8 +207,8 @@ collection_name = os.environ[ "MONGODB_COLLECTION_NAME"] index_name = os.environ["MONGODB_INDEX_NAME"] vector_path = os.environ["MONGODB_VECTOR_PATH"] -# Initialize the vector store driver -vector_store = MongoDbAtlasVectorStoreDriver( +# Initialize the Vector Store Driver +vector_store_driver = MongoDbAtlasVectorStoreDriver( connection_string=f"mongodb+srv://{username}:{password}@{host}/{database_name}", database_name=database_name, collection_name=collection_name, @@ -183,18 +217,21 @@ vector_store = MongoDbAtlasVectorStoreDriver( vector_path=vector_path, ) -# Load artifacts from the web +# Load Artifacts from the web artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") -# Upsert the artifacts into the vector store -vector_store.upsert_text_artifacts( +# Upsert Artifacts into the Vector Store Driver +vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store.query(query="What is griptape?") -print(result) +results =vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` The format for creating a vector index should look similar to the following: @@ -219,18 +256,18 @@ Replace `path_to_vector` with the expected field name where the vector content w ### Azure MongoDB !!! info - This driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). + This Driver requires the `drivers-vector-mongodb` [extra](../index.md#extras). The [AzureMongoDbVectorStoreDriver](../../reference/griptape/drivers/vector/azure_mongodb_vector_store_driver.md) provides support for storing vector data in an Azure CosmosDb database account using the MongoDb vCore API -Here is an example of how the driver can be used to load and query information in an Azure CosmosDb MongoDb vCore database. It is very similar to the Driver for [MongoDb Atlas](#mongodb-atlas): +Here is an example of how the Driver can be used to load and query information in an Azure CosmosDb MongoDb vCore database. It is very similar to the Driver for [MongoDb Atlas](#mongodb-atlas): ```python from griptape.drivers import AzureMongoDbVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader import os -# Initialize an embedding driver +# Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) azure_host = os.environ["AZURE_MONGODB_HOST"] @@ -241,8 +278,8 @@ collection_name = os.environ["AZURE_MONGODB_COLLECTION_NAME"] index_name = os.environ["AZURE_MONGODB_INDEX_NAME"] vector_path = os.environ["AZURE_MONGODB_VECTOR_PATH"] -# Initialize the vector store driver -vector_store = AzureMongoDbVectorStoreDriver( +# Initialize the Vector Store Driver +vector_store_driver = AzureMongoDbVectorStoreDriver( connection_string=f"mongodb+srv://{username}:{password}@{azure_host}/{database_name}?tls=true&authMechanism=SCRAM-SHA-256&retrywrites=false&maxIdleTimeMS=120000", database_name=database_name, collection_name=collection_name, @@ -251,28 +288,31 @@ vector_store = AzureMongoDbVectorStoreDriver( vector_path=vector_path, ) -# Load artifacts from the web +# Load Artifacts from the web artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") -# Upsert the artifacts into the vector store -vector_store.upsert_text_artifacts( +# Upsert Artifacts into the Vector Store Driver +vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store.query(query="What is griptape?") -print(result) +results =vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` ### Redis !!! info - This driver requires the `drivers-vector-redis` [extra](../index.md#extras). + This Driver requires the `drivers-vector-redis` [extra](../index.md#extras). The [RedisVectorStoreDriver](../../reference/griptape/drivers/vector/redis_vector_store_driver.md) integrates with the Redis vector storage system. -Here is an example of how the driver can be used to load and query information in a Redis Cluster: +Here is an example of how the Driver can be used to load and query information in a Redis Cluster: ```python import os @@ -280,7 +320,7 @@ from griptape.drivers import RedisVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader import numpy as np # Assuming you'd use numpy to create a dummy vector for the sake of example. -# Initialize an embedding driver +# Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) vector_store_driver = RedisVectorStoreDriver( @@ -291,18 +331,21 @@ vector_store_driver = RedisVectorStoreDriver( embedding_driver=embedding_driver, ) -# Load artifacts from the web +# Load Artifacts from the web artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") -# Upsert the artifacts into the vector store +# Upsert Artifacts into the Vector Store Driver vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store_driver.query(query="What is griptape?") -print(result) +results =vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` The format for creating a vector index should be similar to the following: @@ -313,11 +356,11 @@ FT.CREATE idx:griptape ON hash PREFIX 1 "griptape:" SCHEMA namespace TAG vector ### OpenSearch !!! info - This driver requires the `drivers-vector-opensearch` [extra](../index.md#extras). + This Driver requires the `drivers-vector-opensearch` [extra](../index.md#extras). The [OpenSearchVectorStoreDriver](../../reference/griptape/drivers/vector/opensearch_vector_store_driver.md) integrates with the OpenSearch platform, allowing for storage, retrieval, and querying of vector data. -Here is an example of how the driver can be used to load and query information in an OpenSearch Cluster: +Here is an example of how the Driver can be used to load and query information in an OpenSearch Cluster: ```python import os @@ -325,7 +368,7 @@ import boto3 from griptape.drivers import AmazonOpenSearchVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader -# Initialize an embedding driver +# Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) vector_store_driver = AmazonOpenSearchVectorStoreDriver( @@ -335,19 +378,21 @@ vector_store_driver = AmazonOpenSearchVectorStoreDriver( embedding_driver=embedding_driver, ) -# Load artifacts from the web +# Load Artifacts from the web artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") -# Upsert the artifacts into the vector store +# Upsert Artifacts into the Vector Store Driver vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store_driver.query(query="What is griptape?") +results =vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] -print(result) +print("\n\n".join(values)) ``` The body mappings for creating a vector index should look similar to the following: @@ -366,18 +411,18 @@ The body mappings for creating a vector index should look similar to the followi ### PGVector !!! info - This driver requires the `drivers-vector-postgresql` [extra](../index.md#extras). + This Driver requires the `drivers-vector-postgresql` [extra](../index.md#extras). -The [PGVectorVectorStoreDriver](../../reference/griptape/drivers/vector/pgvector_vector_store_driver.md) integrates with PGVector, a vector storage and search extension for Postgres. While Griptape will handle enabling the extension, PGVector must be installed and ready for use in your Postgres instance before using this vector store driver. +The [PGVectorVectorStoreDriver](../../reference/griptape/drivers/vector/pgvector_vector_store_driver.md) integrates with PGVector, a vector storage and search extension for Postgres. While Griptape will handle enabling the extension, PGVector must be installed and ready for use in your Postgres instance before using this Vector Store Driver. -Here is an example of how the driver can be used to load and query information in a Postgres database: +Here is an example of how the Driver can be used to load and query information in a Postgres database: ```python import os from griptape.drivers import PgVectorVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader -# Initialize an embedding driver. +# Initialize an Embedding Driver. embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) db_user = os.environ["POSTGRES_USER"] @@ -395,26 +440,31 @@ vector_store_driver = PgVectorVectorStoreDriver( # Install required Postgres extensions and create database schema. vector_store_driver.setup() -web_loader = WebLoader() -artifacts = web_loader.load("https://www.griptape.ai") +# Load Artifacts from the web +artifacts = WebLoader().load("https://www.griptape.ai") + +# Upsert Artifacts into the Vector Store Driver vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store_driver.query("What is griptape?") -print(result) +results =vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` ### Qdrant !!! info - This driver requires the `drivers-vector-qdrant` [extra](../index.md#extras). + This Driver requires the `drivers-vector-qdrant` [extra](../index.md#extras). The QdrantVectorStoreDriver supports the [Qdrant vector database](https://qdrant.tech/). -Here is an example of how the driver can be used to query information in a Qdrant collection: +Here is an example of how the Driver can be used to query information in a Qdrant collection: ```python import os @@ -427,14 +477,14 @@ embedding_model_name = "sentence-transformers/all-MiniLM-L6-v2" host = os.environ["QDRANT_CLUSTER_ENDPOINT"] huggingface_token = os.environ["HUGGINGFACE_HUB_ACCESS_TOKEN"] -# Initialize HuggingFace embedding driver +# Initialize HuggingFace Embedding Driver embedding_driver = HuggingFaceHubEmbeddingDriver( api_token=huggingface_token, model=embedding_model_name, tokenizer=HuggingFaceTokenizer(model=embedding_model_name, max_output_tokens=512), ) -# Initialize Qdrant vector store driver +# Initialize Qdrant Vector Store Driver vector_store_driver = QdrantVectorStoreDriver( url=host, collection_name="griptape", @@ -443,7 +493,7 @@ vector_store_driver = QdrantVectorStoreDriver( api_key=os.environ["QDRANT_CLUSTER_API_KEY"], ) -# Load data from the website +# Load Artifacts from the web artifacts = WebLoader().load("https://www.griptape.ai") # Encode text to get embeddings @@ -465,6 +515,9 @@ vector_store_driver.upsert_vector( content=artifacts[0].value ) -print("Vectors successfully inserted into Qdrant.") +results =vector_store_driver.query(query="What is griptape?") +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 4e0fe6672..4ecb6c9bd 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -41,6 +41,7 @@ from .vector.azure_mongodb_vector_store_driver import AzureMongoDbVectorStoreDriver from .vector.dummy_vector_store_driver import DummyVectorStoreDriver from .vector.qdrant_vector_store_driver import QdrantVectorStoreDriver +from .vector.griptape_cloud_knowledge_base_vector_store_driver import GriptapeCloudKnowledgeBaseVectorStoreDriver from .sql.base_sql_driver import BaseSqlDriver from .sql.amazon_redshift_sql_driver import AmazonRedshiftSqlDriver @@ -149,6 +150,7 @@ "PgVectorVectorStoreDriver", "QdrantVectorStoreDriver", "DummyVectorStoreDriver", + "GriptapeCloudKnowledgeBaseVectorStoreDriver", "BaseSqlDriver", "AmazonRedshiftSqlDriver", "SnowflakeSqlDriver", diff --git a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py new file mode 100644 index 000000000..0c7d5c961 --- /dev/null +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -0,0 +1,101 @@ +from urllib.parse import urljoin +import requests +from typing import Optional, Any +from attrs import Factory, define, field +from griptape.artifacts import TextArtifact, ListArtifact +from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver + + +@define +class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): + """A vector store driver for Griptape Cloud Knowledge Bases. + + Attributes: + api_key: API Key for Griptape Cloud. + knowledge_base_id: Knowledge Base ID for Griptape Cloud. + base_url: Base URL for Griptape Cloud. + headers: Headers for Griptape Cloud. + """ + + api_key: str = field(kw_only=True, metadata={"serializable": True}) + knowledge_base_id: str = field(kw_only=True, metadata={"serializable": True}) + base_url: str = field(default="https://cloud.griptape.ai", kw_only=True) + headers: dict = field( + default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True + ) + embedding_driver: BaseEmbeddingDriver = field( + default=Factory(lambda: DummyEmbeddingDriver()), metadata={"serializable": True}, kw_only=True, init=False + ) + + def upsert_vector( + self, + vector: list[float], + vector_id: Optional[str] = None, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + **kwargs, + ) -> str: + raise NotImplementedError(f"{self.__class__.__name__} does not support vector upsert.") + + def upsert_text_artifact( + self, + artifact: TextArtifact, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + vector_id: Optional[str] = None, + **kwargs, + ) -> str: + raise NotImplementedError(f"{self.__class__.__name__} does not support text artifact upsert.") + + def upsert_text( + self, + string: str, + vector_id: Optional[str] = None, + namespace: Optional[str] = None, + meta: Optional[dict] = None, + **kwargs, + ) -> str: + raise NotImplementedError(f"{self.__class__.__name__} does not support text upsert.") + + def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> BaseVectorStoreDriver.Entry: + raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") + + def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") + + def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: + raise NotImplementedError(f"{self.__class__.__name__} does not support Artifact loading.") + + def query( + self, + query: str, + count: Optional[int] = None, + namespace: Optional[str] = None, + include_vectors: Optional[bool] = None, + distance_metric: Optional[str] = None, + # GriptapeCloudKnowledgeBaseVectorStoreDriver-specific params: + filter: Optional[dict] = None, + **kwargs, + ) -> list[BaseVectorStoreDriver.Entry]: + """Performs a query on the Knowledge Base. + + Performs a query on the Knowledge Base and returns Artifacts with close vector proximity to the query, optionally filtering to only those that match the provided filter(s). + """ + url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") + + request: dict[str, Any] = { + "query": query, + "count": count, + "distance_metric": distance_metric, + "filter": filter, + "include_vectors": include_vectors, + } + request = {k: v for k, v in request.items() if v is not None} + + response = requests.post(url, json=request, headers=self.headers).json() + entries = response.get("entries", []) + entry_list = [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] + return entry_list + + def delete_vector(self, vector_id: str): + raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") diff --git a/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py b/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py new file mode 100644 index 000000000..957edebb8 --- /dev/null +++ b/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py @@ -0,0 +1,69 @@ +import pytest +import uuid +from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver + + +class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: + test_ids = [str(uuid.uuid4()), str(uuid.uuid4())] + test_vecs = [[0.1, 0.2, 0.3], [0.4, 0.5, 0.6]] + test_namespaces = [str(uuid.uuid4()), str(uuid.uuid4())] + test_metas = [{"key": "value1"}, {"key": "value2"}] + test_scores = [0.7, 0.8] + + @pytest.fixture + def driver(self, mocker): + test_entries = { + "entries": [ + { + "id": self.test_ids[0], + "vector": self.test_vecs[0], + "namespace": self.test_namespaces[0], + "meta": self.test_metas[0], + "score": self.test_scores[0], + }, + { + "id": self.test_ids[1], + "vector": self.test_vecs[1], + "namespace": self.test_namespaces[1], + "meta": self.test_metas[1], + "score": self.test_scores[1], + }, + ] + } + + mock_response = mocker.Mock() + mock_response.status_code = 200 + mock_response.json.return_value = test_entries + mocker.patch("requests.post", return_value=mock_response) + + return GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key="foo bar", knowledge_base_id="1") + + def test_query(self, driver): + result = driver.query( + "some query", count=10, namespace="foo", include_vectors=True, distance_metric="bar", filter={"foo": "bar"} + ) + + assert result[0].id == self.test_ids[0] + assert result[1].id == self.test_ids[1] + assert result[0].vector == self.test_vecs[0] + assert result[1].vector == self.test_vecs[1] + assert result[0].namespace == self.test_namespaces[0] + assert result[1].namespace == self.test_namespaces[1] + assert result[0].meta == self.test_metas[0] + assert result[1].meta == self.test_metas[1] + assert result[0].score == self.test_scores[0] + assert result[1].score == self.test_scores[1] + + def test_query_defaults(self, driver): + result = driver.query("some query") + + assert result[0].id == self.test_ids[0] + assert result[1].id == self.test_ids[1] + assert result[0].vector == self.test_vecs[0] + assert result[1].vector == self.test_vecs[1] + assert result[0].namespace == self.test_namespaces[0] + assert result[1].namespace == self.test_namespaces[1] + assert result[0].meta == self.test_metas[0] + assert result[1].meta == self.test_metas[1] + assert result[0].score == self.test_scores[0] + assert result[1].score == self.test_scores[1] From 3bf5876457529e2660940f57b23b0f7f9b6621fe Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Fri, 12 Jul 2024 14:15:46 -0700 Subject: [PATCH 62/87] Add ruff rule for pygrep-hooks (#966) --- griptape/artifacts/list_artifact.py | 2 +- griptape/chunkers/base_chunker.py | 2 +- .../griptape_cloud_event_listener_driver.py | 2 +- .../file_manager/amazon_s3_file_manager_driver.py | 2 +- .../drivers/file_manager/local_file_manager_driver.py | 2 +- .../prompt/amazon_sagemaker_jumpstart_prompt_driver.py | 2 +- griptape/drivers/sql/amazon_redshift_sql_driver.py | 2 +- griptape/drivers/sql/snowflake_sql_driver.py | 4 ++-- ...riptape_cloud_knowledge_base_vector_store_driver.py | 6 ++++-- .../drivers/vector/pgvector_vector_store_driver.py | 6 +++--- griptape/drivers/vector/redis_vector_store_driver.py | 2 +- griptape/engines/extraction/base_extraction_engine.py | 2 +- griptape/engines/rag/stages/base_rag_stage.py | 3 ++- griptape/engines/rag/stages/query_rag_stage.py | 5 +++-- griptape/engines/summary/prompt_summary_engine.py | 2 +- griptape/memory/task/storage/text_artifact_storage.py | 2 +- griptape/memory/task/task_memory.py | 2 +- griptape/mixins/activity_mixin.py | 4 ++-- griptape/mixins/media_artifact_file_output_mixin.py | 4 ++-- griptape/mixins/rule_mixin.py | 4 ++-- griptape/schemas/polymorphic_schema.py | 6 +++--- griptape/structures/agent.py | 2 +- griptape/structures/structure.py | 10 +++++----- griptape/tasks/base_image_generation_task.py | 4 ++-- griptape/tasks/toolkit_task.py | 2 +- griptape/tools/base_google_client.py | 4 ++-- griptape/tools/base_tool.py | 2 +- griptape/tools/calculator/tool.py | 2 +- griptape/tools/computer/tool.py | 2 +- griptape/utils/chat.py | 4 ++-- griptape/utils/stream.py | 2 +- pyproject.toml | 1 + 32 files changed, 53 insertions(+), 48 deletions(-) diff --git a/griptape/artifacts/list_artifact.py b/griptape/artifacts/list_artifact.py index 23cca6461..9af86aa40 100644 --- a/griptape/artifacts/list_artifact.py +++ b/griptape/artifacts/list_artifact.py @@ -12,7 +12,7 @@ class ListArtifact(BaseArtifact): item_separator: str = field(default="\n\n", kw_only=True, metadata={"serializable": True}) validate_uniform_types: bool = field(default=False, kw_only=True, metadata={"serializable": True}) - @value.validator # pyright: ignore + @value.validator # pyright: ignore[reportAttributeAccessIssue] def validate_value(self, _, value: list[BaseArtifact]) -> None: if self.validate_uniform_types and len(value) > 0: first_type = type(value[0]) diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index a6258d43b..bf298baf4 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -24,7 +24,7 @@ class BaseChunker(ABC): default=Factory(lambda self: self.tokenizer.max_input_tokens, takes_self=True), kw_only=True ) - @max_tokens.validator # pyright: ignore + @max_tokens.validator # pyright: ignore[reportAttributeAccessIssue] def validate_max_tokens(self, _, max_tokens: int) -> None: if max_tokens < 0: raise ValueError("max_tokens must be 0 or greater.") diff --git a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py index 0ecf17d9b..e89ab6da0 100644 --- a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py +++ b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py @@ -29,7 +29,7 @@ class GriptapeCloudEventListenerDriver(BaseEventListenerDriver): ) structure_run_id: str = field(default=Factory(lambda: os.getenv("GT_CLOUD_STRUCTURE_RUN_ID")), kw_only=True) - @structure_run_id.validator # pyright: ignore + @structure_run_id.validator # pyright: ignore[reportAttributeAccessIssue] def validate_run_id(self, _, structure_run_id: str): if structure_run_id is None: raise ValueError( diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index d9eae9696..84e49ecd3 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -31,7 +31,7 @@ class AmazonS3FileManagerDriver(BaseFileManagerDriver): workdir: str = field(default="/", kw_only=True) s3_client: Any = field(default=Factory(lambda self: self.session.client("s3"), takes_self=True), kw_only=True) - @workdir.validator # pyright: ignore + @workdir.validator # pyright: ignore[reportAttributeAccessIssue] def validate_workdir(self, _, workdir: str) -> None: if not Path(workdir).is_absolute(): raise ValueError("Workdir must be an absolute path") diff --git a/griptape/drivers/file_manager/local_file_manager_driver.py b/griptape/drivers/file_manager/local_file_manager_driver.py index 3dea4612b..ad681e24b 100644 --- a/griptape/drivers/file_manager/local_file_manager_driver.py +++ b/griptape/drivers/file_manager/local_file_manager_driver.py @@ -18,7 +18,7 @@ class LocalFileManagerDriver(BaseFileManagerDriver): workdir: str = field(default=Factory(lambda: os.getcwd()), kw_only=True) - @workdir.validator # pyright: ignore + @workdir.validator # pyright: ignore[reportAttributeAccessIssue] def validate_workdir(self, _, workdir: str) -> None: if not Path(workdir).is_absolute(): raise ValueError("Workdir must be an absolute path") diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 9eafed64a..6bc83954e 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -37,7 +37,7 @@ class AmazonSageMakerJumpstartPromptDriver(BasePromptDriver): kw_only=True, ) - @stream.validator # pyright: ignore + @stream.validator # pyright: ignore[reportAttributeAccessIssue] def validate_stream(self, _, stream): if stream: raise ValueError("streaming is not supported") diff --git a/griptape/drivers/sql/amazon_redshift_sql_driver.py b/griptape/drivers/sql/amazon_redshift_sql_driver.py index edb7d39cb..00391dc63 100644 --- a/griptape/drivers/sql/amazon_redshift_sql_driver.py +++ b/griptape/drivers/sql/amazon_redshift_sql_driver.py @@ -24,7 +24,7 @@ class AmazonRedshiftSqlDriver(BaseSqlDriver): default=Factory(lambda self: self.session.client("redshift-data"), takes_self=True), kw_only=True ) - @workgroup_name.validator # pyright: ignore + @workgroup_name.validator # pyright: ignore[reportAttributeAccessIssue] def validate_params(self, _, workgroup_name: Optional[str]) -> None: if not self.cluster_identifier and not self.workgroup_name: raise ValueError("Provide a value for one of `cluster_identifier` or `workgroup_name`") diff --git a/griptape/drivers/sql/snowflake_sql_driver.py b/griptape/drivers/sql/snowflake_sql_driver.py index 2b89ec720..7af4c78cc 100644 --- a/griptape/drivers/sql/snowflake_sql_driver.py +++ b/griptape/drivers/sql/snowflake_sql_driver.py @@ -27,7 +27,7 @@ class SnowflakeSqlDriver(BaseSqlDriver): kw_only=True, ) - @connection_func.validator # pyright: ignore + @connection_func.validator # pyright: ignore[reportFunctionMemberAccess] def validate_connection_func(self, _, connection_func: Callable[[], SnowflakeConnection]) -> None: snowflake_connection = connection_func() snowflake = import_optional_dependency("snowflake") @@ -37,7 +37,7 @@ def validate_connection_func(self, _, connection_func: Callable[[], SnowflakeCon if not snowflake_connection.schema or not snowflake_connection.database: raise ValueError("Provide a schema and database for the Snowflake connection") - @engine.validator # pyright: ignore + @engine.validator # pyright: ignore[reportAttributeAccessIssue] def validate_engine_url(self, _, engine: Engine) -> None: if not engine.url.render_as_string().startswith("snowflake://"): raise ValueError("Provide a Snowflake connection") diff --git a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py index 0c7d5c961..416d5e258 100644 --- a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -1,8 +1,10 @@ +from typing import Any, Optional from urllib.parse import urljoin + import requests -from typing import Optional, Any from attrs import Factory, define, field -from griptape.artifacts import TextArtifact, ListArtifact + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index 3b3e5646f..01747c35e 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -31,7 +31,7 @@ class PgVectorVectorStoreDriver(BaseVectorStoreDriver): table_name: str = field(kw_only=True, metadata={"serializable": True}) _model: Any = field(default=Factory(lambda self: self.default_vector_model(), takes_self=True)) - @connection_string.validator # pyright: ignore + @connection_string.validator # pyright: ignore[reportAttributeAccessIssue] def validate_connection_string(self, _, connection_string: Optional[str]) -> None: # If an engine is provided, the connection string is not used. if self.engine is not None: @@ -44,7 +44,7 @@ def validate_connection_string(self, _, connection_string: Optional[str]) -> Non if not connection_string.startswith("postgresql://"): raise ValueError("The connection string must describe a Postgres database connection") - @engine.validator # pyright: ignore + @engine.validator # pyright: ignore[reportAttributeAccessIssue] def validate_engine(self, _, engine: Optional[Engine]) -> None: # If a connection string is provided, an engine does not need to be provided. if self.connection_string is not None: @@ -141,7 +141,7 @@ def query( vector = self.embedding_driver.embed_string(query) # The query should return both the vector and the distance metric score. - query_result = session.query(self._model, op(vector).label("score")).order_by(op(vector)) # pyright: ignore + query_result = session.query(self._model, op(vector).label("score")).order_by(op(vector)) # pyright: ignore[reportOptionalCall] filter_kwargs: Optional[OrderedDict] = None diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index 35a171cee..3008760b2 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -134,7 +134,7 @@ def query( query_params = {"vector": np.array(vector, dtype=np.float32).tobytes()} - results = self.client.ft(self.index).search(query_expression, query_params).docs # pyright: ignore + results = self.client.ft(self.index).search(query_expression, query_params).docs # pyright: ignore[reportArgumentType] query_results = [] for document in results: diff --git a/griptape/engines/extraction/base_extraction_engine.py b/griptape/engines/extraction/base_extraction_engine.py index cad3680bd..e1974ca9e 100644 --- a/griptape/engines/extraction/base_extraction_engine.py +++ b/griptape/engines/extraction/base_extraction_engine.py @@ -26,7 +26,7 @@ class BaseExtractionEngine(ABC): kw_only=True, ) - @max_token_multiplier.validator # pyright: ignore + @max_token_multiplier.validator # pyright: ignore[reportAttributeAccessIssue] def validate_max_token_multiplier(self, _, max_token_multiplier: int) -> None: if max_token_multiplier > 1: raise ValueError("has to be less than or equal to 1") diff --git a/griptape/engines/rag/stages/base_rag_stage.py b/griptape/engines/rag/stages/base_rag_stage.py index 8c94405e0..5484f6193 100644 --- a/griptape/engines/rag/stages/base_rag_stage.py +++ b/griptape/engines/rag/stages/base_rag_stage.py @@ -1,4 +1,5 @@ from abc import ABC, abstractmethod +from collections.abc import Sequence from concurrent import futures from typing import Callable @@ -19,4 +20,4 @@ def run(self, context: RagContext) -> RagContext: ... @property @abstractmethod - def modules(self) -> list[BaseRagModule]: ... + def modules(self) -> Sequence[BaseRagModule]: ... diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py index 35f5df371..a131230ef 100644 --- a/griptape/engines/rag/stages/query_rag_stage.py +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -1,4 +1,5 @@ import logging +from collections.abc import Sequence from attrs import define, field @@ -13,8 +14,8 @@ class QueryRagStage(BaseRagStage): query_modules: list[BaseQueryRagModule] = field() @property - def modules(self) -> list[BaseRagModule]: - return self.query_modules # pyright: ignore + def modules(self) -> Sequence[BaseRagModule]: + return self.query_modules def run(self, context: RagContext) -> RagContext: logging.info(f"QueryStage: running {len(self.query_modules)} query generation modules in parallel") diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 01823ed08..1447c3c97 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -27,7 +27,7 @@ class PromptSummaryEngine(BaseSummaryEngine): kw_only=True, ) - @max_token_multiplier.validator # pyright: ignore + @max_token_multiplier.validator # pyright: ignore[reportAttributeAccessIssue] def validate_allowlist(self, _, max_token_multiplier: int) -> None: if max_token_multiplier > 1: raise ValueError("has to be less than or equal to 1") diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index f6bcf93d5..9bbf83433 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -22,7 +22,7 @@ class TextArtifactStorage(BaseArtifactStorage): csv_extraction_engine: Optional[CsvExtractionEngine] = field(default=None) json_extraction_engine: Optional[JsonExtractionEngine] = field(default=None) - @rag_engine.validator # pyright: ignore + @rag_engine.validator # pyright: ignore[reportAttributeAccessIssue] def validate_rag_engine(self, _, rag_engine: str) -> None: if rag_engine is not None and self.retrieval_rag_module_name is None: raise ValueError("You have to set retrieval_rag_module_name if rag_engine is provided") diff --git a/griptape/memory/task/task_memory.py b/griptape/memory/task/task_memory.py index 2c3075576..2e0639adc 100644 --- a/griptape/memory/task/task_memory.py +++ b/griptape/memory/task/task_memory.py @@ -20,7 +20,7 @@ class TaskMemory(ActivityMixin): namespace_storage: dict[str, BaseArtifactStorage] = field(factory=dict, kw_only=True) namespace_metadata: dict[str, Any] = field(factory=dict, kw_only=True) - @artifact_storages.validator # pyright: ignore + @artifact_storages.validator # pyright: ignore[reportAttributeAccessIssue] def validate_artifact_storages(self, _, artifact_storage: dict[type, BaseArtifactStorage]) -> None: seen_types = [] diff --git a/griptape/mixins/activity_mixin.py b/griptape/mixins/activity_mixin.py index 31f398482..7730e1b43 100644 --- a/griptape/mixins/activity_mixin.py +++ b/griptape/mixins/activity_mixin.py @@ -12,7 +12,7 @@ class ActivityMixin: allowlist: Optional[list[str]] = field(default=None, kw_only=True) denylist: Optional[list[str]] = field(default=None, kw_only=True) - @allowlist.validator # pyright: ignore + @allowlist.validator # pyright: ignore[reportAttributeAccessIssue] def validate_allowlist(self, _, allowlist: Optional[list[str]]) -> None: if allowlist is None: return @@ -23,7 +23,7 @@ def validate_allowlist(self, _, allowlist: Optional[list[str]]) -> None: for activity_name in allowlist: self._validate_tool_activity(activity_name) - @denylist.validator # pyright: ignore + @denylist.validator # pyright: ignore[reportAttributeAccessIssue] def validate_denylist(self, _, denylist: Optional[list[str]]) -> None: if denylist is None: return diff --git a/griptape/mixins/media_artifact_file_output_mixin.py b/griptape/mixins/media_artifact_file_output_mixin.py index b2a0d8ef9..36907634b 100644 --- a/griptape/mixins/media_artifact_file_output_mixin.py +++ b/griptape/mixins/media_artifact_file_output_mixin.py @@ -14,7 +14,7 @@ class BlobArtifactFileOutputMixin: output_dir: Optional[str] = field(default=None, kw_only=True) output_file: Optional[str] = field(default=None, kw_only=True) - @output_dir.validator # pyright: ignore + @output_dir.validator # pyright: ignore[reportAttributeAccessIssue] def validate_output_dir(self, _, output_dir: str) -> None: if not output_dir: return @@ -22,7 +22,7 @@ def validate_output_dir(self, _, output_dir: str) -> None: if self.output_file: raise ValueError("Can't have both output_dir and output_file specified.") - @output_file.validator # pyright: ignore + @output_file.validator # pyright: ignore[reportAttributeAccessIssue] def validate_output_file(self, _, output_file: str) -> None: if not output_file: return diff --git a/griptape/mixins/rule_mixin.py b/griptape/mixins/rule_mixin.py index 04a487505..920c17c5b 100644 --- a/griptape/mixins/rule_mixin.py +++ b/griptape/mixins/rule_mixin.py @@ -19,7 +19,7 @@ class RuleMixin: rules: list[Rule] = field(factory=list, kw_only=True) structure: Optional[Structure] = field(default=None, kw_only=True) - @rulesets.validator # pyright: ignore + @rulesets.validator # pyright: ignore[reportAttributeAccessIssue] def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: if not rulesets: return @@ -27,7 +27,7 @@ def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: if self.rules: raise ValueError("Can't have both rulesets and rules specified.") - @rules.validator # pyright: ignore + @rules.validator # pyright: ignore[reportAttributeAccessIssue] def validate_rules(self, _, rules: list[Rule]) -> None: if not rules: return diff --git a/griptape/schemas/polymorphic_schema.py b/griptape/schemas/polymorphic_schema.py index 3fd7450ff..87772539c 100644 --- a/griptape/schemas/polymorphic_schema.py +++ b/griptape/schemas/polymorphic_schema.py @@ -49,7 +49,7 @@ def dump(self, obj, *, many=None, **kwargs): if not errors: return result else: - exc = ValidationError(errors, data=obj, valid_data=result) # pyright: ignore + exc = ValidationError(errors, data=obj, valid_data=result) # pyright: ignore[reportArgumentType] raise exc def _dump(self, obj, *, update_fields=True, **kwargs): @@ -70,7 +70,7 @@ def _dump(self, obj, *, update_fields=True, **kwargs): result = schema.dump(obj, many=False, **kwargs) if result is not None: - result[self.type_field] = obj_type # pyright: ignore + result[self.type_field] = obj_type # pyright: ignore[reportArgumentType,reportCallIssue] return result @@ -127,7 +127,7 @@ def _load(self, data, *, partial=None, unknown=None, **kwargs): return schema.load(data, many=False, partial=partial, unknown=unknown, **kwargs) - def validate(self, data, *, many=None, partial=None): # pyright: ignore + def validate(self, data, *, many=None, partial=None): # pyright: ignore[reportIncompatibleMethodOverride] try: self.load(data, many=many, partial=partial) except ValidationError as ve: diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 5d4c3054a..1392bfb27 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -24,7 +24,7 @@ class Agent(Structure): max_meta_memory_entries: Optional[int] = field(default=20, kw_only=True) fail_fast: bool = field(default=False, kw_only=True) - @fail_fast.validator # pyright: ignore + @fail_fast.validator # pyright: ignore[reportAttributeAccessIssue] def validate_fail_fast(self, _, fail_fast: bool) -> None: if fail_fast: raise ValueError("Agents cannot fail fast, as they can only have 1 task.") diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index fb6cd25cd..144394732 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -69,7 +69,7 @@ class Structure(ABC): _execution_args: tuple = () _logger: Optional[Logger] = None - @rulesets.validator # pyright: ignore + @rulesets.validator # pyright: ignore[reportAttributeAccessIssue] def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: if not rulesets: return @@ -77,7 +77,7 @@ def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: if self.rules: raise ValueError("can't have both rulesets and rules specified") - @rules.validator # pyright: ignore + @rules.validator # pyright: ignore[reportAttributeAccessIssue] def validate_rules(self, _, rules: list[Rule]) -> None: if not rules: return @@ -96,17 +96,17 @@ def __attrs_post_init__(self) -> None: def __add__(self, other: BaseTask | list[BaseTask]) -> list[BaseTask]: return self.add_tasks(*other) if isinstance(other, list) else self + [other] - @prompt_driver.validator # pyright: ignore + @prompt_driver.validator # pyright: ignore[reportAttributeAccessIssue] def validate_prompt_driver(self, attribute, value): if value is not None: deprecation_warn(f"`{attribute.name}` is deprecated, use `config.prompt_driver` instead.") - @embedding_driver.validator # pyright: ignore + @embedding_driver.validator # pyright: ignore[reportAttributeAccessIssue] def validate_embedding_driver(self, attribute, value): if value is not None: deprecation_warn(f"`{attribute.name}` is deprecated, use `config.embedding_driver` instead.") - @stream.validator # pyright: ignore + @stream.validator # pyright: ignore[reportAttributeAccessIssue] def validate_stream(self, attribute, value): if value is not None: deprecation_warn(f"`{attribute.name}` is deprecated, use `config.prompt_driver.stream` instead.") diff --git a/griptape/tasks/base_image_generation_task.py b/griptape/tasks/base_image_generation_task.py index 74cf2d04e..a6e8ad8ef 100644 --- a/griptape/tasks/base_image_generation_task.py +++ b/griptape/tasks/base_image_generation_task.py @@ -31,7 +31,7 @@ class BaseImageGenerationTask(BlobArtifactFileOutputMixin, RuleMixin, BaseTask, negative_rulesets: list[Ruleset] = field(factory=list, kw_only=True) negative_rules: list[Rule] = field(factory=list, kw_only=True) - @negative_rulesets.validator # pyright: ignore + @negative_rulesets.validator # pyright: ignore[reportAttributeAccessIssue] def validate_negative_rulesets(self, _, negative_rulesets: list[Ruleset]) -> None: if not negative_rulesets: return @@ -39,7 +39,7 @@ def validate_negative_rulesets(self, _, negative_rulesets: list[Ruleset]) -> Non if self.negative_rules: raise ValueError("Can't have both negative_rulesets and negative_rules specified.") - @negative_rules.validator # pyright: ignore + @negative_rules.validator # pyright: ignore[reportAttributeAccessIssue] def validate_negative_rules(self, _, negative_rules: list[Rule]) -> None: if not negative_rules: return diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index 6306fa7b3..9132f53f5 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -43,7 +43,7 @@ def __attrs_post_init__(self) -> None: if self.task_memory: self.set_default_tools_memory(self.task_memory) - @tools.validator # pyright: ignore + @tools.validator # pyright: ignore[reportAttributeAccessIssue] def validate_tools(self, _, tools: list[BaseTool]) -> None: tool_names = [t.name for t in tools] diff --git a/griptape/tools/base_google_client.py b/griptape/tools/base_google_client.py index 4a15770ec..63e6f0b31 100644 --- a/griptape/tools/base_google_client.py +++ b/griptape/tools/base_google_client.py @@ -15,8 +15,8 @@ class BaseGoogleClient(BaseTool, ABC): service_account_credentials: dict = field(kw_only=True) def _build_client(self, scopes: list[str], service_name: str, version: str, owner_email: str) -> Any: - from google.oauth2 import service_account # pyright: ignore - from googleapiclient.discovery import build # pyright: ignore + from google.oauth2 import service_account + from googleapiclient.discovery import build credentials = service_account.Credentials.from_service_account_info( self.service_account_credentials, scopes=scopes diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 1e71e6a8f..b9cc21cdf 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -50,7 +50,7 @@ def __attrs_post_init__(self) -> None: if self.install_dependencies_on_init: self.install_dependencies(os.environ.copy()) - @output_memory.validator # pyright: ignore + @output_memory.validator # pyright: ignore[reportAttributeAccessIssue] def validate_output_memory(self, _, output_memory: dict[str, Optional[list[TaskMemory]]]) -> None: if output_memory: for activity_name, memory_list in output_memory.items(): diff --git a/griptape/tools/calculator/tool.py b/griptape/tools/calculator/tool.py index 02e5fe95e..04d6868e3 100644 --- a/griptape/tools/calculator/tool.py +++ b/griptape/tools/calculator/tool.py @@ -21,7 +21,7 @@ class Calculator(BaseTool): } ) def calculate(self, params: dict) -> BaseArtifact: - import numexpr # type: ignore + import numexpr try: expression = params["values"]["expression"] diff --git a/griptape/tools/computer/tool.py b/griptape/tools/computer/tool.py index 565389a3f..06129bfd6 100644 --- a/griptape/tools/computer/tool.py +++ b/griptape/tools/computer/tool.py @@ -50,7 +50,7 @@ def __attrs_post_init__(self) -> None: self._tempdir = tempfile.TemporaryDirectory() self.local_workdir = self._tempdir.name - @docker_client.validator # pyright: ignore + @docker_client.validator # pyright: ignore[reportAttributeAccessIssue] def validate_docker_client(self, _, docker_client: DockerClient) -> None: if not docker_client: raise ValueError("Docker client can't be initialized: make sure the Docker daemon is running") diff --git a/griptape/utils/chat.py b/griptape/utils/chat.py index f78d311f9..032938706 100644 --- a/griptape/utils/chat.py +++ b/griptape/utils/chat.py @@ -25,9 +25,9 @@ class Chat: def default_output_fn(self, text: str) -> None: if self.structure.config.prompt_driver.stream: - print(text, end="", flush=True) # noqa T201 + print(text, end="", flush=True) # noqa: T201 else: - print(text) # noqa T201 + print(text) # noqa: T201 def start(self) -> None: if self.intro_text: diff --git a/griptape/utils/stream.py b/griptape/utils/stream.py index 32e31ea7b..64f94e943 100644 --- a/griptape/utils/stream.py +++ b/griptape/utils/stream.py @@ -35,7 +35,7 @@ class Stream: structure: Structure = field() - @structure.validator # pyright: ignore + @structure.validator # pyright: ignore[reportAttributeAccessIssue] def validate_structure(self, _, structure: Structure): if structure and not structure.config.prompt_driver.stream: raise ValueError("prompt driver does not have streaming enabled, enable with stream=True") diff --git a/pyproject.toml b/pyproject.toml index 6e0b43917..e462fc7c6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -212,6 +212,7 @@ select = [ "C901", # complex-structure "TCH", # flake8-type-checking "D", # pydocstyle + "PGH", # pygrep-hooks "I" # isort ] ignore = [ From 7d95861ec020c432768ae7996d9e38a4e11c3248 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Fri, 12 Jul 2024 14:16:00 -0700 Subject: [PATCH 63/87] Fix inserting conversation into when no system content is present. (#969) --- CHANGELOG.md | 4 ++++ .../memory/structure/base_conversation_memory.py | 6 +++--- griptape/tasks/prompt_task.py | 6 +++--- tests/unit/tasks/test_prompt_task.py | 16 ++++++++++++++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 816c0707c..72b7b1b67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [0.28.2] - 2024-07-12 +### Fixed +- Conversation Memory being incorrectly inserted into the `PromptTask.prompt_stack` when no system content is present. + ## [0.28.1] - 2024-07-10 ### Fixed diff --git a/griptape/memory/structure/base_conversation_memory.py b/griptape/memory/structure/base_conversation_memory.py index a8133d64b..aa5c8d40a 100644 --- a/griptape/memory/structure/base_conversation_memory.py +++ b/griptape/memory/structure/base_conversation_memory.py @@ -88,9 +88,9 @@ def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = if num_runs_to_fit_in_prompt: memory_inputs = self.to_prompt_stack(num_runs_to_fit_in_prompt).messages - if index: - prompt_stack.messages[index:index] = memory_inputs - else: + if index is None: prompt_stack.messages.extend(memory_inputs) + else: + prompt_stack.messages[index:index] = memory_inputs return prompt_stack diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index c428e092d..bee32090f 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -51,9 +51,9 @@ def prompt_stack(self) -> PromptStack: if self.output: stack.add_assistant_message(self.output) - if memory: - # inserting at index 1 to place memory right after system prompt - memory.add_to_prompt_stack(stack, 1) + if memory is not None: + # insert memory into the stack right before the user messages + memory.add_to_prompt_stack(stack, 1 if system_template else 0) return stack diff --git a/tests/unit/tasks/test_prompt_task.py b/tests/unit/tasks/test_prompt_task.py index 7f9cb3302..c76f0284b 100644 --- a/tests/unit/tasks/test_prompt_task.py +++ b/tests/unit/tasks/test_prompt_task.py @@ -2,6 +2,8 @@ from griptape.artifacts.image_artifact import ImageArtifact from griptape.artifacts.list_artifact import ListArtifact from griptape.artifacts.text_artifact import TextArtifact +from griptape.memory.structure import ConversationMemory +from griptape.memory.structure.run import Run from tests.mocks.mock_structure_config import MockStructureConfig from griptape.tasks import PromptTask from griptape.rules import Rule @@ -136,7 +138,17 @@ def test_prompt_stack(self): def test_prompt_stack_empty_system_content(self): task = PromptTask("{{ test }}", context={"test": "test value"}) - Pipeline().add_task(task) + pipeline = Pipeline( + conversation_memory=ConversationMemory( + runs=[Run(input=TextArtifact("input"), output=TextArtifact("output"))] + ) + ) + pipeline.add_task(task) - assert len(task.prompt_stack.messages) == 1 + assert len(task.prompt_stack.messages) == 3 assert task.prompt_stack.messages[0].is_user() + assert task.prompt_stack.messages[0].to_text() == "input" + assert task.prompt_stack.messages[1].is_assistant() + assert task.prompt_stack.messages[1].to_text() == "output" + assert task.prompt_stack.messages[2].is_user() + assert task.prompt_stack.messages[2].to_text() == "test value" From 4a294695f89ed8957fbee6c06fd31f03cc20f0f0 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Fri, 12 Jul 2024 15:49:42 -0700 Subject: [PATCH 64/87] Version bump v0.28.2 (#971) --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9090da332..77c323480 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "griptape" -version = "0.28.1" +version = "0.28.2" description = "Modular Python framework for LLM workflows, tools, memory, and data." authors = ["Griptape "] license = "Apache 2.0" From 0a8e178e70791ac324dbcac67edc7eb258f0eb70 Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Fri, 12 Jul 2024 23:47:02 -0700 Subject: [PATCH 65/87] Fix: Qdrant query count not optional (#972) --- CHANGELOG.md | 1 + .../drivers/vector-store-drivers.md | 96 +++++-------------- .../vector/qdrant_vector_store_driver.py | 4 +- 3 files changed, 30 insertions(+), 71 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97c34314a..a8d6002e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed ### Fixed +- Parameter `count` for `QdrantVectorStoreDriver.query` now optional as per documentation. ## [0.28.2] - 2024-07-12 ### Fixed diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index ea2b72a56..c1f54ab2e 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -24,7 +24,6 @@ The [LocalVectorStoreDriver](../../reference/griptape/drivers/vector/local_vecto ```python import os -from griptape.artifacts import BaseArtifact from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader @@ -40,16 +39,11 @@ artifacts = WebLoader(max_tokens=100).load("https://www.griptape.ai") # Upsert Artifacts into the Vector Store Driver [vector_store_driver.upsert_text_artifact(a, namespace="griptape") for a in artifacts] -results = vector_store_driver.query( - "creativity", - count=3, - namespace="griptape" -) +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] print("\n\n".join(values)) - ``` ### Griptape Cloud Knowledge Base @@ -58,7 +52,6 @@ The [GriptapeCloudKnowledgeBaseVectorStoreDriver](../../reference/griptape/drive ```python import os -from griptape.artifacts import BaseArtifact from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver @@ -68,12 +61,11 @@ gt_cloud_knowledge_base_id = os.environ["GRIPTAPE_CLOUD_KB_ID"] vector_store_driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key=gt_cloud_api_key, knowledge_base_id=gt_cloud_knowledge_base_id) -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] print("\n\n".join(values)) - ``` ### Pinecone @@ -86,31 +78,10 @@ The [PineconeVectorStoreDriver](../../reference/griptape/drivers/vector/pinecone Here is an example of how the Driver can be used to load and query information in a Pinecone cluster: ```python -import os -import hashlib -import json -from urllib.request import urlopen +import os from griptape.drivers import PineconeVectorStoreDriver, OpenAiEmbeddingDriver +from griptape.loaders import WebLoader -def load_data(driver: PineconeVectorStoreDriver) -> None: - response = urlopen( - "https://raw.githubusercontent.com/wedeploy-examples/" - "supermarket-web-example/master/products.json" - ) - - for product in json.loads(response.read()): - driver.upsert_text( - product["description"], - vector_id=hashlib.md5(product["title"].encode()).hexdigest(), - meta={ - "title": product["title"], - "description": product["description"], - "type": product["type"], - "price": product["price"], - "rating": product["rating"], - }, - namespace="supermarket-products", - ) # Initialize an Embedding Driver embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) @@ -118,18 +89,17 @@ embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) vector_store_driver = PineconeVectorStoreDriver( api_key=os.environ["PINECONE_API_KEY"], environment=os.environ["PINECONE_ENVIRONMENT"], - index_name=os.environ['PINECONE_INDEX_NAME'], + index_name=os.environ["PINECONE_INDEX_NAME"], embedding_driver=embedding_driver, ) -load_data(vector_store_driver) +# Load Artifacts from the web +artifacts = WebLoader(max_tokens=100).load("https://www.griptape.ai") -results = vector_store_driver.query( - "fruit", - count=3, - filter={"price": {"$lte": 15}, "rating": {"$gte": 4}}, - namespace="supermarket-products", -) +# Upsert Artifacts into the Vector Store Driver +[vector_store_driver.upsert_text_artifact(a, namespace="griptape") for a in artifacts] + +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] @@ -175,7 +145,7 @@ vector_store_driver.upsert_text_artifacts( } ) -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] @@ -227,7 +197,7 @@ vector_store_driver.upsert_text_artifacts( } ) -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] @@ -298,7 +268,7 @@ vector_store_driver.upsert_text_artifacts( } ) -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] @@ -341,7 +311,7 @@ vector_store_driver.upsert_text_artifacts( } ) -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] @@ -388,7 +358,7 @@ vector_store_driver.upsert_text_artifacts( } ) -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] @@ -450,7 +420,7 @@ vector_store_driver.upsert_text_artifacts( } ) -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] @@ -468,54 +438,40 @@ Here is an example of how the Driver can be used to query information in a Qdran ```python import os -from griptape.drivers import QdrantVectorStoreDriver, HuggingFaceHubEmbeddingDriver -from griptape.tokenizers import HuggingFaceTokenizer +from griptape.drivers import QdrantVectorStoreDriver, OpenAiEmbeddingDriver from griptape.loaders import WebLoader # Set up environment variables -embedding_model_name = "sentence-transformers/all-MiniLM-L6-v2" host = os.environ["QDRANT_CLUSTER_ENDPOINT"] -huggingface_token = os.environ["HUGGINGFACE_HUB_ACCESS_TOKEN"] +api_key = os.environ["QDRANT_CLUSTER_API_KEY"] -# Initialize HuggingFace Embedding Driver -embedding_driver = HuggingFaceHubEmbeddingDriver( - api_token=huggingface_token, - model=embedding_model_name, - tokenizer=HuggingFaceTokenizer(model=embedding_model_name, max_output_tokens=512), -) +# Initialize an Embedding Driver. +embedding_driver = OpenAiEmbeddingDriver(api_key=os.environ["OPENAI_API_KEY"]) -# Initialize Qdrant Vector Store Driver vector_store_driver = QdrantVectorStoreDriver( url=host, collection_name="griptape", content_payload_key="content", embedding_driver=embedding_driver, - api_key=os.environ["QDRANT_CLUSTER_API_KEY"], + api_key=api_key, ) # Load Artifacts from the web artifacts = WebLoader().load("https://www.griptape.ai") -# Encode text to get embeddings -embeddings = embedding_driver.embed_text_artifact(artifacts[0]) - # Recreate Qdrant collection vector_store_driver.client.recreate_collection( collection_name=vector_store_driver.collection_name, vectors_config={ - "size": len(embeddings), + "size": 1536, "distance": vector_store_driver.distance }, ) -# Upsert vector into Qdrant -vector_store_driver.upsert_vector( - vector=embeddings, - vector_id=str(artifacts[0].id), - content=artifacts[0].value -) +# Upsert Artifacts into the Vector Store Driver +[vector_store_driver.upsert_text_artifact(a, namespace="griptape") for a in artifacts] -results =vector_store_driver.query(query="What is griptape?") +results = vector_store_driver.query(query="What is griptape?") values = [r.to_artifact().value for r in results] diff --git a/griptape/drivers/vector/qdrant_vector_store_driver.py b/griptape/drivers/vector/qdrant_vector_store_driver.py index 34345b6df..a5162f754 100644 --- a/griptape/drivers/vector/qdrant_vector_store_driver.py +++ b/griptape/drivers/vector/qdrant_vector_store_driver.py @@ -106,7 +106,9 @@ def query( query_vector = self.embedding_driver.embed_string(query) # Create a search request - results = self.client.search(collection_name=self.collection_name, query_vector=query_vector, limit=count) + request = {"collection_name": self.collection_name, "query_vector": query_vector, "limit": count} + request = {k: v for k, v in request.items() if v is not None} + results = self.client.search(**request) # Convert results to QueryResult objects query_results = [ From e4f8d6fe66d360cf19f57a13d99e8082a3feb76f Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 15 Jul 2024 09:34:35 -0700 Subject: [PATCH 66/87] Add flake8-future-annotations ruff rule (#973) --- griptape/artifacts/list_artifact.py | 8 ++++++-- griptape/common/reference.py | 2 ++ .../config/azure_openai_structure_config.py | 2 ++ griptape/config/structure_config.py | 2 ++ .../dummy_audio_transcription_driver.py | 8 ++++++-- .../embedding/dummy_embedding_driver.py | 2 ++ .../dummy_image_generation_driver.py | 8 ++++++-- .../leonardo_image_generation_driver.py | 2 ++ .../image_query/dummy_image_query_driver.py | 8 +++++++- .../local_conversation_memory_driver.py | 2 ++ .../prompt/azure_openai_chat_prompt_driver.py | 8 ++++++-- griptape/drivers/rerank/base_rerank_driver.py | 6 +++++- griptape/drivers/sql/base_sql_driver.py | 2 ++ .../base_structure_run_driver.py | 6 +++++- .../dummy_text_to_speech_driver.py | 8 +++++++- .../vector/dummy_vector_store_driver.py | 2 ++ ...loud_knowledge_base_vector_store_driver.py | 8 ++++++-- .../vector/local_vector_store_driver.py | 2 ++ .../vector/pgvector_vector_store_driver.py | 2 ++ .../markdownify_web_scraper_driver.py | 2 ++ .../web_search/google_web_search_driver.py | 2 ++ .../engines/image_query/image_query_engine.py | 9 +++++++-- .../engines/rag/modules/base_rag_module.py | 8 ++++++-- .../footnote_prompt_response_rag_module.py | 10 ++++++++-- .../metadata_before_response_rag_module.py | 8 ++++++-- .../response/prompt_response_rag_module.py | 10 +++++++--- .../rulesets_before_response_rag_module.py | 10 ++++++++-- griptape/engines/rag/rag_engine.py | 8 ++++++-- .../engines/rag/stages/query_rag_stage.py | 12 +++++++++--- .../engines/rag/stages/response_rag_stage.py | 19 ++++++++++++------- .../engines/rag/stages/retrieval_rag_stage.py | 10 +++++++--- .../engines/summary/base_summary_engine.py | 8 ++++++-- .../engines/summary/prompt_summary_engine.py | 10 +++++++--- griptape/events/finish_prompt_event.py | 2 ++ griptape/events/finish_structure_run_event.py | 8 ++++++-- griptape/events/start_image_query_event.py | 2 ++ griptape/events/start_structure_run_event.py | 8 ++++++-- griptape/loaders/sql_loader.py | 8 ++++++-- griptape/memory/meta/meta_memory.py | 7 ++++++- .../task/storage/blob_artifact_storage.py | 2 ++ griptape/mixins/activity_mixin.py | 2 ++ griptape/mixins/exponential_backoff_mixin.py | 2 ++ griptape/rules/ruleset.py | 7 ++++++- griptape/schemas/base_schema.py | 2 ++ griptape/tools/base_google_client.py | 2 ++ griptape/tools/rest_api_client/tool.py | 2 ++ griptape/utils/dict_utils.py | 2 ++ griptape/utils/file_utils.py | 2 ++ griptape/utils/futures.py | 2 ++ griptape/utils/import_utils.py | 8 ++++++-- griptape/utils/j2.py | 2 ++ griptape/utils/python_runner.py | 2 ++ griptape/utils/reference_utils.py | 9 +++++++-- pyproject.toml | 3 ++- 54 files changed, 238 insertions(+), 60 deletions(-) diff --git a/griptape/artifacts/list_artifact.py b/griptape/artifacts/list_artifact.py index 9af86aa40..8590f57d3 100644 --- a/griptape/artifacts/list_artifact.py +++ b/griptape/artifacts/list_artifact.py @@ -1,10 +1,14 @@ -from collections.abc import Sequence -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional from attrs import define, field from griptape.artifacts import BaseArtifact +if TYPE_CHECKING: + from collections.abc import Sequence + @define class ListArtifact(BaseArtifact): diff --git a/griptape/common/reference.py b/griptape/common/reference.py index 40b709df9..66a62b83f 100644 --- a/griptape/common/reference.py +++ b/griptape/common/reference.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import uuid from typing import Optional diff --git a/griptape/config/azure_openai_structure_config.py b/griptape/config/azure_openai_structure_config.py index 8361c7894..712815416 100644 --- a/griptape/config/azure_openai_structure_config.py +++ b/griptape/config/azure_openai_structure_config.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Callable, Optional from attrs import Factory, define, field diff --git a/griptape/config/structure_config.py b/griptape/config/structure_config.py index fe7bc7342..0c2ed9743 100644 --- a/griptape/config/structure_config.py +++ b/griptape/config/structure_config.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Optional from attrs import Factory, define, field diff --git a/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py b/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py index ba3da3231..9fc44b4b9 100644 --- a/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py +++ b/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py @@ -1,11 +1,15 @@ -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional from attrs import define, field -from griptape.artifacts import AudioArtifact, TextArtifact from griptape.drivers import BaseAudioTranscriptionDriver from griptape.exceptions import DummyException +if TYPE_CHECKING: + from griptape.artifacts import AudioArtifact, TextArtifact + @define class DummyAudioTranscriptionDriver(BaseAudioTranscriptionDriver): diff --git a/griptape/drivers/embedding/dummy_embedding_driver.py b/griptape/drivers/embedding/dummy_embedding_driver.py index dadd02897..09171060e 100644 --- a/griptape/drivers/embedding/dummy_embedding_driver.py +++ b/griptape/drivers/embedding/dummy_embedding_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from attrs import define, field from griptape.drivers import BaseEmbeddingDriver diff --git a/griptape/drivers/image_generation/dummy_image_generation_driver.py b/griptape/drivers/image_generation/dummy_image_generation_driver.py index ac1961821..788280a11 100644 --- a/griptape/drivers/image_generation/dummy_image_generation_driver.py +++ b/griptape/drivers/image_generation/dummy_image_generation_driver.py @@ -1,11 +1,15 @@ -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional from attrs import define, field -from griptape.artifacts import ImageArtifact from griptape.drivers import BaseImageGenerationDriver from griptape.exceptions import DummyException +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact + @define class DummyImageGenerationDriver(BaseImageGenerationDriver): diff --git a/griptape/drivers/image_generation/leonardo_image_generation_driver.py b/griptape/drivers/image_generation/leonardo_image_generation_driver.py index 44d583683..6b6cdc61f 100644 --- a/griptape/drivers/image_generation/leonardo_image_generation_driver.py +++ b/griptape/drivers/image_generation/leonardo_image_generation_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import time from typing import Literal, Optional diff --git a/griptape/drivers/image_query/dummy_image_query_driver.py b/griptape/drivers/image_query/dummy_image_query_driver.py index 43d481c68..1df1c4c65 100644 --- a/griptape/drivers/image_query/dummy_image_query_driver.py +++ b/griptape/drivers/image_query/dummy_image_query_driver.py @@ -1,9 +1,15 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.artifacts import ImageArtifact, TextArtifact from griptape.drivers import BaseImageQueryDriver from griptape.exceptions import DummyException +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact, TextArtifact + @define class DummyImageQueryDriver(BaseImageQueryDriver): diff --git a/griptape/drivers/memory/conversation/local_conversation_memory_driver.py b/griptape/drivers/memory/conversation/local_conversation_memory_driver.py index b94bd3065..d8c7e992e 100644 --- a/griptape/drivers/memory/conversation/local_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/local_conversation_memory_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os from typing import Optional diff --git a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py index 0f8c76ea9..dca64763b 100644 --- a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py @@ -1,11 +1,15 @@ -from typing import Callable, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Callable, Optional import openai from attrs import Factory, define, field -from griptape.common import PromptStack from griptape.drivers import OpenAiChatPromptDriver +if TYPE_CHECKING: + from griptape.common import PromptStack + @define class AzureOpenAiChatPromptDriver(OpenAiChatPromptDriver): diff --git a/griptape/drivers/rerank/base_rerank_driver.py b/griptape/drivers/rerank/base_rerank_driver.py index 8193a108d..c49e0f41b 100644 --- a/griptape/drivers/rerank/base_rerank_driver.py +++ b/griptape/drivers/rerank/base_rerank_driver.py @@ -1,8 +1,12 @@ +from __future__ import annotations + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING from attrs import define -from griptape.artifacts import TextArtifact +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact @define(kw_only=True) diff --git a/griptape/drivers/sql/base_sql_driver.py b/griptape/drivers/sql/base_sql_driver.py index db05615b9..0a872ebdc 100644 --- a/griptape/drivers/sql/base_sql_driver.py +++ b/griptape/drivers/sql/base_sql_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from abc import ABC, abstractmethod from dataclasses import dataclass from typing import Any, Optional diff --git a/griptape/drivers/structure_run/base_structure_run_driver.py b/griptape/drivers/structure_run/base_structure_run_driver.py index 5bf2c9a5f..9dfc6c8ce 100644 --- a/griptape/drivers/structure_run/base_structure_run_driver.py +++ b/griptape/drivers/structure_run/base_structure_run_driver.py @@ -1,8 +1,12 @@ +from __future__ import annotations + from abc import ABC, abstractmethod +from typing import TYPE_CHECKING from attrs import Factory, define, field -from griptape.artifacts import BaseArtifact +if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact @define diff --git a/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py b/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py index bfef900c5..6472bdff8 100644 --- a/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py @@ -1,9 +1,15 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.artifacts.audio_artifact import AudioArtifact from griptape.drivers import BaseTextToSpeechDriver from griptape.exceptions import DummyException +if TYPE_CHECKING: + from griptape.artifacts.audio_artifact import AudioArtifact + @define class DummyTextToSpeechDriver(BaseTextToSpeechDriver): diff --git a/griptape/drivers/vector/dummy_vector_store_driver.py b/griptape/drivers/vector/dummy_vector_store_driver.py index d1a6fdf0e..998b7a747 100644 --- a/griptape/drivers/vector/dummy_vector_store_driver.py +++ b/griptape/drivers/vector/dummy_vector_store_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Optional from attrs import Factory, define, field diff --git a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py index 416d5e258..2f3417f04 100644 --- a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -1,12 +1,16 @@ -from typing import Any, Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Optional from urllib.parse import urljoin import requests from attrs import Factory, define, field -from griptape.artifacts import ListArtifact, TextArtifact from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver +if TYPE_CHECKING: + from griptape.artifacts import ListArtifact, TextArtifact + @define class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): diff --git a/griptape/drivers/vector/local_vector_store_driver.py b/griptape/drivers/vector/local_vector_store_driver.py index 2ed76056e..f855f4228 100644 --- a/griptape/drivers/vector/local_vector_store_driver.py +++ b/griptape/drivers/vector/local_vector_store_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import os import threading diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index 01747c35e..61c789243 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import uuid from collections import OrderedDict from dataclasses import dataclass diff --git a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py index 3945c786a..92d2c6244 100644 --- a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import re from typing import Optional diff --git a/griptape/drivers/web_search/google_web_search_driver.py b/griptape/drivers/web_search/google_web_search_driver.py index 16d024f77..6d08a9561 100644 --- a/griptape/drivers/web_search/google_web_search_driver.py +++ b/griptape/drivers/web_search/google_web_search_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json import requests diff --git a/griptape/engines/image_query/image_query_engine.py b/griptape/engines/image_query/image_query_engine.py index 9cb61cd92..d0a1e99d4 100644 --- a/griptape/engines/image_query/image_query_engine.py +++ b/griptape/engines/image_query/image_query_engine.py @@ -1,7 +1,12 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.artifacts import ImageArtifact, TextArtifact -from griptape.drivers import BaseImageQueryDriver +if TYPE_CHECKING: + from griptape.artifacts import ImageArtifact, TextArtifact + from griptape.drivers import BaseImageQueryDriver @define diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py index 527fa8ad6..c90ed182c 100644 --- a/griptape/engines/rag/modules/base_rag_module.py +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -1,11 +1,15 @@ +from __future__ import annotations + from abc import ABC from concurrent import futures -from typing import Any, Callable, Optional +from typing import TYPE_CHECKING, Any, Callable, Optional from attrs import Factory, define, field from griptape.common import Message, PromptStack -from griptape.engines.rag import RagContext + +if TYPE_CHECKING: + from griptape.engines.rag import RagContext @define(kw_only=True) diff --git a/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py b/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py index c64c8e5ee..3687d1942 100644 --- a/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py +++ b/griptape/engines/rag/modules/response/footnote_prompt_response_rag_module.py @@ -1,11 +1,17 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define from griptape import utils -from griptape.artifacts import TextArtifact -from griptape.engines.rag import RagContext from griptape.engines.rag.modules import PromptResponseRagModule from griptape.utils import J2 +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact + from griptape.engines.rag import RagContext + @define(kw_only=True) class FootnotePromptResponseRagModule(PromptResponseRagModule): diff --git a/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py index 7e88a3a8a..d2d546213 100644 --- a/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py +++ b/griptape/engines/rag/modules/response/metadata_before_response_rag_module.py @@ -1,11 +1,15 @@ -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional from attrs import define, field -from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseBeforeResponseRagModule from griptape.utils import J2 +if TYPE_CHECKING: + from griptape.engines.rag import RagContext + @define(kw_only=True) class MetadataBeforeResponseRagModule(BaseBeforeResponseRagModule): diff --git a/griptape/engines/rag/modules/response/prompt_response_rag_module.py b/griptape/engines/rag/modules/response/prompt_response_rag_module.py index 915b430d8..7f9b4daf8 100644 --- a/griptape/engines/rag/modules/response/prompt_response_rag_module.py +++ b/griptape/engines/rag/modules/response/prompt_response_rag_module.py @@ -1,13 +1,17 @@ -from typing import Callable +from __future__ import annotations + +from typing import TYPE_CHECKING, Callable from attrs import Factory, define, field from griptape.artifacts.text_artifact import TextArtifact -from griptape.drivers import BasePromptDriver -from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseResponseRagModule from griptape.utils import J2 +if TYPE_CHECKING: + from griptape.drivers import BasePromptDriver + from griptape.engines.rag import RagContext + @define(kw_only=True) class PromptResponseRagModule(BaseResponseRagModule): diff --git a/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py index eb22807a6..81b8410ce 100644 --- a/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py +++ b/griptape/engines/rag/modules/response/rulesets_before_response_rag_module.py @@ -1,10 +1,16 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.engines.rag import RagContext from griptape.engines.rag.modules import BaseBeforeResponseRagModule -from griptape.rules import Ruleset from griptape.utils import J2 +if TYPE_CHECKING: + from griptape.engines.rag import RagContext + from griptape.rules import Ruleset + @define class RulesetsBeforeResponseRagModule(BaseBeforeResponseRagModule): diff --git a/griptape/engines/rag/rag_engine.py b/griptape/engines/rag/rag_engine.py index 9fdb13384..b3533bdba 100644 --- a/griptape/engines/rag/rag_engine.py +++ b/griptape/engines/rag/rag_engine.py @@ -1,9 +1,13 @@ -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional from attrs import define, field from griptape.engines.rag import RagContext -from griptape.engines.rag.stages import QueryRagStage, ResponseRagStage, RetrievalRagStage + +if TYPE_CHECKING: + from griptape.engines.rag.stages import QueryRagStage, ResponseRagStage, RetrievalRagStage @define(kw_only=True) diff --git a/griptape/engines/rag/stages/query_rag_stage.py b/griptape/engines/rag/stages/query_rag_stage.py index a131230ef..5f9ccd019 100644 --- a/griptape/engines/rag/stages/query_rag_stage.py +++ b/griptape/engines/rag/stages/query_rag_stage.py @@ -1,13 +1,19 @@ +from __future__ import annotations + import logging -from collections.abc import Sequence +from typing import TYPE_CHECKING from attrs import define, field from griptape import utils -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseQueryRagModule, BaseRagModule from griptape.engines.rag.stages import BaseRagStage +if TYPE_CHECKING: + from collections.abc import Sequence + + from griptape.engines.rag import RagContext + from griptape.engines.rag.modules import BaseQueryRagModule, BaseRagModule + @define(kw_only=True) class QueryRagStage(BaseRagStage): diff --git a/griptape/engines/rag/stages/response_rag_stage.py b/griptape/engines/rag/stages/response_rag_stage.py index d6467bbb5..ac4451a34 100644 --- a/griptape/engines/rag/stages/response_rag_stage.py +++ b/griptape/engines/rag/stages/response_rag_stage.py @@ -1,16 +1,21 @@ +from __future__ import annotations + import logging +from typing import TYPE_CHECKING from attrs import define, field -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import ( - BaseAfterResponseRagModule, - BaseBeforeResponseRagModule, - BaseRagModule, - BaseResponseRagModule, -) from griptape.engines.rag.stages import BaseRagStage +if TYPE_CHECKING: + from griptape.engines.rag import RagContext + from griptape.engines.rag.modules import ( + BaseAfterResponseRagModule, + BaseBeforeResponseRagModule, + BaseRagModule, + BaseResponseRagModule, + ) + @define(kw_only=True) class ResponseRagStage(BaseRagStage): diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py index f65d92f57..8f552af3a 100644 --- a/griptape/engines/rag/stages/retrieval_rag_stage.py +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -1,15 +1,19 @@ +from __future__ import annotations + import itertools import logging -from typing import Optional +from typing import TYPE_CHECKING, Optional from attrs import define, field from griptape import utils from griptape.artifacts import TextArtifact -from griptape.engines.rag import RagContext -from griptape.engines.rag.modules import BaseRagModule, BaseRerankRagModule, BaseRetrievalRagModule from griptape.engines.rag.stages import BaseRagStage +if TYPE_CHECKING: + from griptape.engines.rag import RagContext + from griptape.engines.rag.modules import BaseRagModule, BaseRerankRagModule, BaseRetrievalRagModule + @define(kw_only=True) class RetrievalRagStage(BaseRagStage): diff --git a/griptape/engines/summary/base_summary_engine.py b/griptape/engines/summary/base_summary_engine.py index 108666bb7..e5ce6ee1e 100644 --- a/griptape/engines/summary/base_summary_engine.py +++ b/griptape/engines/summary/base_summary_engine.py @@ -1,10 +1,14 @@ +from __future__ import annotations + from abc import ABC, abstractmethod -from typing import Optional +from typing import TYPE_CHECKING, Optional from attrs import define from griptape.artifacts import ListArtifact, TextArtifact -from griptape.rules import Ruleset + +if TYPE_CHECKING: + from griptape.rules import Ruleset @define diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 1447c3c97..61fe2c2ea 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -1,4 +1,6 @@ -from typing import Optional, cast +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional, cast from attrs import Factory, define, field @@ -6,11 +8,13 @@ from griptape.chunkers import BaseChunker, TextChunker from griptape.common import PromptStack from griptape.common.prompt_stack.messages.message import Message -from griptape.drivers import BasePromptDriver from griptape.engines import BaseSummaryEngine -from griptape.rules import Ruleset from griptape.utils import J2 +if TYPE_CHECKING: + from griptape.drivers import BasePromptDriver + from griptape.rules import Ruleset + @define class PromptSummaryEngine(BaseSummaryEngine): diff --git a/griptape/events/finish_prompt_event.py b/griptape/events/finish_prompt_event.py index 25f658a0f..f8a0b6885 100644 --- a/griptape/events/finish_prompt_event.py +++ b/griptape/events/finish_prompt_event.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Optional from attrs import define, field diff --git a/griptape/events/finish_structure_run_event.py b/griptape/events/finish_structure_run_event.py index 588a5be31..3a7aeddb0 100644 --- a/griptape/events/finish_structure_run_event.py +++ b/griptape/events/finish_structure_run_event.py @@ -1,10 +1,14 @@ -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional from attrs import define, field -from griptape.artifacts import BaseArtifact from griptape.events.base_event import BaseEvent +if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact + @define class FinishStructureRunEvent(BaseEvent): diff --git a/griptape/events/start_image_query_event.py b/griptape/events/start_image_query_event.py index 46001a43f..8deeaaa5a 100644 --- a/griptape/events/start_image_query_event.py +++ b/griptape/events/start_image_query_event.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from attrs import define, field from griptape.events.base_image_query_event import BaseImageQueryEvent diff --git a/griptape/events/start_structure_run_event.py b/griptape/events/start_structure_run_event.py index f0bb5528c..cc3989575 100644 --- a/griptape/events/start_structure_run_event.py +++ b/griptape/events/start_structure_run_event.py @@ -1,10 +1,14 @@ -from typing import Optional +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional from attrs import define, field -from griptape.artifacts import BaseArtifact from griptape.events.base_event import BaseEvent +if TYPE_CHECKING: + from griptape.artifacts import BaseArtifact + @define class StartStructureRunEvent(BaseEvent): diff --git a/griptape/loaders/sql_loader.py b/griptape/loaders/sql_loader.py index 2ac621a82..e4522796f 100644 --- a/griptape/loaders/sql_loader.py +++ b/griptape/loaders/sql_loader.py @@ -1,11 +1,15 @@ -from typing import Optional, cast +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional, cast from attrs import define, field from griptape.artifacts import CsvRowArtifact -from griptape.drivers import BaseEmbeddingDriver, BaseSqlDriver from griptape.loaders import BaseLoader +if TYPE_CHECKING: + from griptape.drivers import BaseEmbeddingDriver, BaseSqlDriver + @define class SqlLoader(BaseLoader): diff --git a/griptape/memory/meta/meta_memory.py b/griptape/memory/meta/meta_memory.py index 2c580de28..66d813e50 100644 --- a/griptape/memory/meta/meta_memory.py +++ b/griptape/memory/meta/meta_memory.py @@ -1,6 +1,11 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.memory.meta import BaseMetaEntry +if TYPE_CHECKING: + from griptape.memory.meta import BaseMetaEntry @define diff --git a/griptape/memory/task/storage/blob_artifact_storage.py b/griptape/memory/task/storage/blob_artifact_storage.py index 25706c079..6199dc3a3 100644 --- a/griptape/memory/task/storage/blob_artifact_storage.py +++ b/griptape/memory/task/storage/blob_artifact_storage.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Any from attrs import define, field diff --git a/griptape/mixins/activity_mixin.py b/griptape/mixins/activity_mixin.py index 7730e1b43..a00a70001 100644 --- a/griptape/mixins/activity_mixin.py +++ b/griptape/mixins/activity_mixin.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import inspect from typing import Callable, Optional diff --git a/griptape/mixins/exponential_backoff_mixin.py b/griptape/mixins/exponential_backoff_mixin.py index fb17a3400..3fb57599d 100644 --- a/griptape/mixins/exponential_backoff_mixin.py +++ b/griptape/mixins/exponential_backoff_mixin.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging from abc import ABC from typing import Callable diff --git a/griptape/rules/ruleset.py b/griptape/rules/ruleset.py index 5d2cca62a..1f158411a 100644 --- a/griptape/rules/ruleset.py +++ b/griptape/rules/ruleset.py @@ -1,6 +1,11 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + from attrs import define, field -from griptape.rules import Rule +if TYPE_CHECKING: + from griptape.rules import Rule @define diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 15dd96b5d..982c155e4 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -101,6 +101,7 @@ def _resolve_types(cls, attrs_cls: type) -> None: Args: attrs_cls: An attrs class. """ + from collections.abc import Sequence from typing import Any from griptape.artifacts import BaseArtifact @@ -160,6 +161,7 @@ def _resolve_types(cls, attrs_cls: type) -> None: "ToolAction": ToolAction, "Reference": Reference, "Run": Run, + "Sequence": Sequence, # Third party modules "Client": Client, "GenerativeModel": GenerativeModel, diff --git a/griptape/tools/base_google_client.py b/griptape/tools/base_google_client.py index 63e6f0b31..1269548f3 100644 --- a/griptape/tools/base_google_client.py +++ b/griptape/tools/base_google_client.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from abc import ABC from typing import Any, Optional diff --git a/griptape/tools/rest_api_client/tool.py b/griptape/tools/rest_api_client/tool.py index fd63ab500..dbd294cd9 100644 --- a/griptape/tools/rest_api_client/tool.py +++ b/griptape/tools/rest_api_client/tool.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from textwrap import dedent from typing import Optional from urllib.parse import urljoin diff --git a/griptape/utils/dict_utils.py b/griptape/utils/dict_utils.py index e142d3bb2..04be605df 100644 --- a/griptape/utils/dict_utils.py +++ b/griptape/utils/dict_utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Optional diff --git a/griptape/utils/file_utils.py b/griptape/utils/file_utils.py index ecefcc6b6..01dd1318a 100644 --- a/griptape/utils/file_utils.py +++ b/griptape/utils/file_utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from concurrent import futures from typing import Optional diff --git a/griptape/utils/futures.py b/griptape/utils/futures.py index d69f4ea48..ea22e4c56 100644 --- a/griptape/utils/futures.py +++ b/griptape/utils/futures.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from concurrent import futures from typing import TypeVar diff --git a/griptape/utils/import_utils.py b/griptape/utils/import_utils.py index 9ad25be20..f0a8c205d 100644 --- a/griptape/utils/import_utils.py +++ b/griptape/utils/import_utils.py @@ -1,6 +1,10 @@ +from __future__ import annotations + from importlib import import_module -from types import ModuleType -from typing import Optional +from typing import TYPE_CHECKING, Optional + +if TYPE_CHECKING: + from types import ModuleType INSTALL_MAPPING = { "huggingface_hub": "huggingface-hub", diff --git a/griptape/utils/j2.py b/griptape/utils/j2.py index 52d7eb69e..70cf936db 100644 --- a/griptape/utils/j2.py +++ b/griptape/utils/j2.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from typing import Optional from attrs import Factory, define, field diff --git a/griptape/utils/python_runner.py b/griptape/utils/python_runner.py index 009d17b7f..0b5c06587 100644 --- a/griptape/utils/python_runner.py +++ b/griptape/utils/python_runner.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import importlib import sys from io import StringIO diff --git a/griptape/utils/reference_utils.py b/griptape/utils/reference_utils.py index 761ee3d24..b036e0eaf 100644 --- a/griptape/utils/reference_utils.py +++ b/griptape/utils/reference_utils.py @@ -1,5 +1,10 @@ -from griptape.artifacts import TextArtifact -from griptape.common import Reference +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from griptape.artifacts import TextArtifact + from griptape.common import Reference def references_from_artifacts(artifacts: list[TextArtifact]) -> list[Reference]: diff --git a/pyproject.toml b/pyproject.toml index d2cf664fc..a1ed38836 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -213,7 +213,8 @@ select = [ "TCH", # flake8-type-checking "D", # pydocstyle "PGH", # pygrep-hooks - "I" # isort + "I", # isort + "FA" # flake8-future-annotations ] ignore = [ "UP007", # non-pep604-annotation From 5edfae92d4d563c0007ae3e0e9c8e2af64c83b1a Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 15 Jul 2024 10:32:42 -0700 Subject: [PATCH 67/87] Add flake8-commas ruff rule (#974) --- griptape/artifacts/base_artifact.py | 4 +- griptape/artifacts/csv_row_artifact.py | 5 +- griptape/chunkers/base_chunker.py | 9 ++- .../common/prompt_stack/messages/message.py | 2 +- .../config/amazon_bedrock_structure_config.py | 3 +- griptape/config/anthropic_structure_config.py | 2 +- .../config/azure_openai_structure_config.py | 4 +- griptape/config/base_structure_config.py | 4 +- griptape/config/cohere_structure_config.py | 4 +- griptape/config/google_structure_config.py | 2 +- griptape/config/openai_structure_config.py | 14 +++-- griptape/config/structure_config.py | 32 +++++++--- .../openai_audio_transcription_driver.py | 2 +- .../amazon_bedrock_cohere_embedding_driver.py | 11 +++- .../amazon_bedrock_titan_embedding_driver.py | 11 +++- ...on_sagemaker_jumpstart_embedding_driver.py | 3 +- .../azure_openai_embedding_driver.py | 13 ++-- .../huggingface_hub_embedding_driver.py | 3 +- .../embedding/openai_embedding_driver.py | 5 +- .../embedding/voyageai_embedding_driver.py | 5 +- .../base_event_listener_driver.py | 3 +- .../griptape_cloud_event_listener_driver.py | 8 ++- .../pusher_event_listener_driver.py | 6 +- .../amazon_s3_file_manager_driver.py | 5 +- .../file_manager/base_file_manager_driver.py | 2 +- .../amazon_bedrock_image_generation_driver.py | 35 ++++++++--- .../azure_openai_image_generation_driver.py | 10 ++- .../base_image_generation_driver.py | 10 ++- .../dummy_image_generation_driver.py | 5 +- .../leonardo_image_generation_driver.py | 21 +++++-- .../openai_image_generation_driver.py | 28 +++++++-- ...diffusion_image_generation_model_driver.py | 6 +- .../amazon_bedrock_image_query_driver.py | 8 ++- .../anthropic_image_query_driver.py | 3 +- .../azure_openai_image_query_driver.py | 10 ++- .../image_query/base_image_query_driver.py | 2 +- .../image_query/openai_image_query_driver.py | 6 +- .../redis_conversation_memory_driver.py | 8 ++- .../prompt/amazon_bedrock_prompt_driver.py | 36 +++++++---- ...mazon_sagemaker_jumpstart_prompt_driver.py | 6 +- .../drivers/prompt/anthropic_prompt_driver.py | 13 ++-- .../prompt/azure_openai_chat_prompt_driver.py | 10 ++- griptape/drivers/prompt/base_prompt_driver.py | 2 +- .../drivers/prompt/cohere_prompt_driver.py | 16 ++--- .../drivers/prompt/google_prompt_driver.py | 35 +++++++---- .../prompt/huggingface_hub_prompt_driver.py | 17 +++-- .../huggingface_pipeline_prompt_driver.py | 16 +++-- .../drivers/prompt/ollama_prompt_driver.py | 6 +- .../prompt/openai_chat_prompt_driver.py | 31 ++++++---- .../drivers/rerank/cohere_rerank_driver.py | 2 +- .../drivers/sql/amazon_redshift_sql_driver.py | 6 +- griptape/drivers/sql/snowflake_sql_driver.py | 3 +- .../griptape_cloud_structure_run_driver.py | 9 ++- .../elevenlabs_text_to_speech_driver.py | 5 +- .../openai_text_to_speech_driver.py | 11 +++- .../amazon_opensearch_vector_store_driver.py | 8 ++- .../azure_mongodb_vector_store_driver.py | 4 +- .../vector/base_vector_store_driver.py | 12 ++-- .../vector/dummy_vector_store_driver.py | 4 +- ...loud_knowledge_base_vector_store_driver.py | 8 ++- .../vector/local_vector_store_driver.py | 5 +- .../vector/marqo_vector_store_driver.py | 5 +- .../mongodb_atlas_vector_store_driver.py | 27 +++++--- .../vector/opensearch_vector_store_driver.py | 9 ++- .../vector/pgvector_vector_store_driver.py | 10 ++- .../vector/pinecone_vector_store_driver.py | 25 ++++++-- .../vector/qdrant_vector_store_driver.py | 8 ++- .../vector/redis_vector_store_driver.py | 10 ++- .../markdownify_web_scraper_driver.py | 5 +- .../trafilatura_web_scraper_driver.py | 5 +- .../duck_duck_go_web_search_driver.py | 4 +- .../web_search/google_web_search_driver.py | 2 +- .../extraction/base_extraction_engine.py | 8 ++- .../extraction/csv_extraction_engine.py | 4 +- .../extraction/json_extraction_engine.py | 8 +-- .../inpainting_image_generation_engine.py | 5 +- .../outpainting_image_generation_engine.py | 5 +- .../variation_image_generation_engine.py | 4 +- .../engines/rag/modules/base_rag_module.py | 4 +- .../response/prompt_response_rag_module.py | 4 +- .../text_loader_retrieval_rag_module.py | 2 +- .../vector_store_retrieval_rag_module.py | 2 +- griptape/engines/rag/stages/base_rag_stage.py | 2 +- .../engines/rag/stages/retrieval_rag_stage.py | 2 +- .../engines/summary/base_summary_engine.py | 5 +- .../engines/summary/prompt_summary_engine.py | 18 +++--- griptape/loaders/base_loader.py | 10 ++- griptape/loaders/base_text_loader.py | 9 ++- griptape/loaders/csv_loader.py | 8 ++- griptape/loaders/pdf_loader.py | 9 ++- griptape/loaders/text_loader.py | 14 +++-- griptape/loaders/web_loader.py | 3 +- .../structure/base_conversation_memory.py | 2 +- .../structure/summary_conversation_memory.py | 5 +- .../task/storage/text_artifact_storage.py | 6 +- griptape/memory/task/task_memory.py | 11 +++- griptape/mixins/activity_mixin.py | 2 +- griptape/structures/agent.py | 2 +- griptape/structures/pipeline.py | 2 +- griptape/structures/structure.py | 19 +++--- griptape/structures/workflow.py | 9 ++- griptape/tasks/actions_subtask.py | 7 ++- griptape/tasks/audio_transcription_task.py | 6 +- griptape/tasks/base_multi_text_input_task.py | 8 ++- griptape/tasks/base_task.py | 7 ++- griptape/tasks/base_text_input_task.py | 3 +- griptape/tasks/image_query_task.py | 2 +- .../tasks/inpainting_image_generation_task.py | 9 ++- .../outpainting_image_generation_task.py | 9 ++- .../tasks/prompt_image_generation_task.py | 10 ++- griptape/tasks/prompt_task.py | 8 ++- griptape/tasks/text_to_speech_task.py | 2 +- griptape/tasks/toolkit_task.py | 20 +++--- .../tasks/variation_image_generation_task.py | 8 ++- griptape/tokenizers/anthropic_tokenizer.py | 3 +- griptape/tokenizers/base_tokenizer.py | 7 ++- griptape/tokenizers/google_tokenizer.py | 3 +- griptape/tokenizers/huggingface_tokenizer.py | 3 +- griptape/tokenizers/openai_tokenizer.py | 11 ++-- griptape/tokenizers/voyageai_tokenizer.py | 3 +- .../tools/audio_transcription_client/tool.py | 7 ++- griptape/tools/aws_iam_client/tool.py | 11 ++-- griptape/tools/aws_s3_client/tool.py | 45 ++++++++------ griptape/tools/base_google_client.py | 3 +- griptape/tools/base_griptape_cloud_client.py | 3 +- griptape/tools/base_tool.py | 16 +++-- griptape/tools/calculator/tool.py | 6 +- griptape/tools/computer/tool.py | 12 ++-- griptape/tools/date_time/tool.py | 6 +- griptape/tools/email_client/tool.py | 14 ++--- griptape/tools/file_manager/tool.py | 20 +++--- griptape/tools/google_cal/tool.py | 16 +++-- griptape/tools/google_docs/tool.py | 51 ++++++++++----- griptape/tools/google_drive/tool.py | 62 ++++++++++++------- griptape/tools/google_gmail/tool.py | 9 ++- .../tool.py | 11 +++- griptape/tools/image_query_client/tool.py | 10 +-- .../tool.py | 33 +++++++--- griptape/tools/openweather_client/tool.py | 14 ++--- .../tool.py | 28 ++++++--- .../prompt_image_generation_client/tool.py | 6 +- griptape/tools/rag_client/tool.py | 2 +- griptape/tools/rest_api_client/tool.py | 28 ++++----- griptape/tools/sql_client/tool.py | 2 +- griptape/tools/structure_run_client/tool.py | 4 +- griptape/tools/task_memory_client/tool.py | 6 +- griptape/tools/text_to_speech_client/tool.py | 2 +- .../variation_image_generation_client/tool.py | 8 +-- griptape/tools/vector_store_client/tool.py | 11 ++-- griptape/tools/web_scraper/tool.py | 2 +- griptape/tools/web_search/tool.py | 6 +- griptape/utils/chat.py | 3 +- griptape/utils/file_utils.py | 2 +- griptape/utils/load_artifact_from_memory.py | 5 +- griptape/utils/stream.py | 3 +- pyproject.toml | 7 +-- 156 files changed, 972 insertions(+), 504 deletions(-) diff --git a/griptape/artifacts/base_artifact.py b/griptape/artifacts/base_artifact.py index ef82110af..249ae48c8 100644 --- a/griptape/artifacts/base_artifact.py +++ b/griptape/artifacts/base_artifact.py @@ -19,7 +19,9 @@ class BaseArtifact(SerializableMixin, ABC): reference: Optional[Reference] = field(default=None, kw_only=True, metadata={"serializable": True}) meta: dict[str, Any] = field(factory=dict, kw_only=True, metadata={"serializable": True}) name: str = field( - default=Factory(lambda self: self.id, takes_self=True), kw_only=True, metadata={"serializable": True} + default=Factory(lambda self: self.id, takes_self=True), + kw_only=True, + metadata={"serializable": True}, ) value: Any = field() diff --git a/griptape/artifacts/csv_row_artifact.py b/griptape/artifacts/csv_row_artifact.py index 74b8f1a4e..ce752e685 100644 --- a/griptape/artifacts/csv_row_artifact.py +++ b/griptape/artifacts/csv_row_artifact.py @@ -19,7 +19,10 @@ def __add__(self, other: BaseArtifact) -> CsvRowArtifact: def to_text(self) -> str: with io.StringIO() as csvfile: writer = csv.DictWriter( - csvfile, fieldnames=self.value.keys(), quoting=csv.QUOTE_MINIMAL, delimiter=self.delimiter + csvfile, + fieldnames=self.value.keys(), + quoting=csv.QUOTE_MINIMAL, + delimiter=self.delimiter, ) writer.writerow(self.value) diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index bf298baf4..4383ce569 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -15,13 +15,16 @@ class BaseChunker(ABC): DEFAULT_SEPARATORS = [ChunkSeparator(" ")] separators: list[ChunkSeparator] = field( - default=Factory(lambda self: self.DEFAULT_SEPARATORS, takes_self=True), kw_only=True + default=Factory(lambda self: self.DEFAULT_SEPARATORS, takes_self=True), + kw_only=True, ) tokenizer: BaseTokenizer = field( - default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)), kw_only=True + default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)), + kw_only=True, ) max_tokens: int = field( - default=Factory(lambda self: self.tokenizer.max_input_tokens, takes_self=True), kw_only=True + default=Factory(lambda self: self.tokenizer.max_input_tokens, takes_self=True), + kw_only=True, ) @max_tokens.validator # pyright: ignore[reportAttributeAccessIssue] diff --git a/griptape/common/prompt_stack/messages/message.py b/griptape/common/prompt_stack/messages/message.py index aaba331d9..4bed14efb 100644 --- a/griptape/common/prompt_stack/messages/message.py +++ b/griptape/common/prompt_stack/messages/message.py @@ -42,7 +42,7 @@ def is_text(self) -> bool: def to_text(self) -> str: return "".join( - [content.artifact.to_text() for content in self.content if isinstance(content, TextMessageContent)] + [content.artifact.to_text() for content in self.content if isinstance(content, TextMessageContent)], ) def to_artifact(self) -> BaseArtifact: diff --git a/griptape/config/amazon_bedrock_structure_config.py b/griptape/config/amazon_bedrock_structure_config.py index c99b59026..3ad7f8f48 100644 --- a/griptape/config/amazon_bedrock_structure_config.py +++ b/griptape/config/amazon_bedrock_structure_config.py @@ -35,7 +35,8 @@ class AmazonBedrockStructureConfig(StructureConfig): prompt_driver: BasePromptDriver = field( default=Factory( lambda self: AmazonBedrockPromptDriver( - session=self.session, model="anthropic.claude-3-5-sonnet-20240620-v1:0" + session=self.session, + model="anthropic.claude-3-5-sonnet-20240620-v1:0", ), takes_self=True, ), diff --git a/griptape/config/anthropic_structure_config.py b/griptape/config/anthropic_structure_config.py index 58db8d476..1bb5bf49b 100644 --- a/griptape/config/anthropic_structure_config.py +++ b/griptape/config/anthropic_structure_config.py @@ -27,7 +27,7 @@ class AnthropicStructureConfig(StructureConfig): ) vector_store_driver: BaseVectorStoreDriver = field( default=Factory( - lambda: LocalVectorStoreDriver(embedding_driver=VoyageAiEmbeddingDriver(model="voyage-large-2")) + lambda: LocalVectorStoreDriver(embedding_driver=VoyageAiEmbeddingDriver(model="voyage-large-2")), ), kw_only=True, metadata={"serializable": True}, diff --git a/griptape/config/azure_openai_structure_config.py b/griptape/config/azure_openai_structure_config.py index 712815416..ce0303e34 100644 --- a/griptape/config/azure_openai_structure_config.py +++ b/griptape/config/azure_openai_structure_config.py @@ -38,7 +38,9 @@ class AzureOpenAiStructureConfig(StructureConfig): azure_endpoint: str = field(kw_only=True, metadata={"serializable": True}) azure_ad_token: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) azure_ad_token_provider: Optional[Callable[[], str]] = field( - kw_only=True, default=None, metadata={"serializable": False} + kw_only=True, + default=None, + metadata={"serializable": False}, ) api_key: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) prompt_driver: BasePromptDriver = field( diff --git a/griptape/config/base_structure_config.py b/griptape/config/base_structure_config.py index a75cb9e80..c2aa82d7e 100644 --- a/griptape/config/base_structure_config.py +++ b/griptape/config/base_structure_config.py @@ -29,7 +29,9 @@ class BaseStructureConfig(BaseConfig, ABC): embedding_driver: BaseEmbeddingDriver = field(kw_only=True, metadata={"serializable": True}) vector_store_driver: BaseVectorStoreDriver = field(kw_only=True, metadata={"serializable": True}) conversation_memory_driver: Optional[BaseConversationMemoryDriver] = field( - default=None, kw_only=True, metadata={"serializable": True} + default=None, + kw_only=True, + metadata={"serializable": True}, ) text_to_speech_driver: BaseTextToSpeechDriver = field(kw_only=True, metadata={"serializable": True}) audio_transcription_driver: BaseAudioTranscriptionDriver = field(kw_only=True, metadata={"serializable": True}) diff --git a/griptape/config/cohere_structure_config.py b/griptape/config/cohere_structure_config.py index c4c9f7eef..2e896b9b0 100644 --- a/griptape/config/cohere_structure_config.py +++ b/griptape/config/cohere_structure_config.py @@ -23,7 +23,9 @@ class CohereStructureConfig(StructureConfig): embedding_driver: BaseEmbeddingDriver = field( default=Factory( lambda self: CohereEmbeddingDriver( - model="embed-english-v3.0", api_key=self.api_key, input_type="search_document" + model="embed-english-v3.0", + api_key=self.api_key, + input_type="search_document", ), takes_self=True, ), diff --git a/griptape/config/google_structure_config.py b/griptape/config/google_structure_config.py index fc0548ff7..66ed90b4b 100644 --- a/griptape/config/google_structure_config.py +++ b/griptape/config/google_structure_config.py @@ -25,7 +25,7 @@ class GoogleStructureConfig(StructureConfig): ) vector_store_driver: BaseVectorStoreDriver = field( default=Factory( - lambda: LocalVectorStoreDriver(embedding_driver=GoogleEmbeddingDriver(model="models/embedding-001")) + lambda: LocalVectorStoreDriver(embedding_driver=GoogleEmbeddingDriver(model="models/embedding-001")), ), kw_only=True, metadata={"serializable": True}, diff --git a/griptape/config/openai_structure_config.py b/griptape/config/openai_structure_config.py index cce828913..63806dfc9 100644 --- a/griptape/config/openai_structure_config.py +++ b/griptape/config/openai_structure_config.py @@ -22,7 +22,9 @@ @define class OpenAiStructureConfig(StructureConfig): prompt_driver: BasePromptDriver = field( - default=Factory(lambda: OpenAiChatPromptDriver(model="gpt-4o")), metadata={"serializable": True}, kw_only=True + default=Factory(lambda: OpenAiChatPromptDriver(model="gpt-4o")), + metadata={"serializable": True}, + kw_only=True, ) image_generation_driver: BaseImageGenerationDriver = field( default=Factory(lambda: OpenAiImageGenerationDriver(model="dall-e-2", image_size="512x512")), @@ -30,7 +32,9 @@ class OpenAiStructureConfig(StructureConfig): metadata={"serializable": True}, ) image_query_driver: BaseImageQueryDriver = field( - default=Factory(lambda: OpenAiImageQueryDriver(model="gpt-4o")), kw_only=True, metadata={"serializable": True} + default=Factory(lambda: OpenAiImageQueryDriver(model="gpt-4o")), + kw_only=True, + metadata={"serializable": True}, ) embedding_driver: BaseEmbeddingDriver = field( default=Factory(lambda: OpenAiEmbeddingDriver(model="text-embedding-3-small")), @@ -39,13 +43,15 @@ class OpenAiStructureConfig(StructureConfig): ) vector_store_driver: BaseVectorStoreDriver = field( default=Factory( - lambda: LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver(model="text-embedding-3-small")) + lambda: LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver(model="text-embedding-3-small")), ), kw_only=True, metadata={"serializable": True}, ) text_to_speech_driver: BaseTextToSpeechDriver = field( - default=Factory(lambda: OpenAiTextToSpeechDriver(model="tts")), kw_only=True, metadata={"serializable": True} + default=Factory(lambda: OpenAiTextToSpeechDriver(model="tts")), + kw_only=True, + metadata={"serializable": True}, ) audio_transcription_driver: BaseAudioTranscriptionDriver = field( default=Factory(lambda: OpenAiAudioTranscriptionDriver(model="whisper-1")), diff --git a/griptape/config/structure_config.py b/griptape/config/structure_config.py index 0c2ed9743..ef95012ce 100644 --- a/griptape/config/structure_config.py +++ b/griptape/config/structure_config.py @@ -27,26 +27,42 @@ @define class StructureConfig(BaseStructureConfig): prompt_driver: BasePromptDriver = field( - kw_only=True, default=Factory(lambda: DummyPromptDriver()), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda: DummyPromptDriver()), + metadata={"serializable": True}, ) image_generation_driver: BaseImageGenerationDriver = field( - kw_only=True, default=Factory(lambda: DummyImageGenerationDriver()), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda: DummyImageGenerationDriver()), + metadata={"serializable": True}, ) image_query_driver: BaseImageQueryDriver = field( - kw_only=True, default=Factory(lambda: DummyImageQueryDriver()), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda: DummyImageQueryDriver()), + metadata={"serializable": True}, ) embedding_driver: BaseEmbeddingDriver = field( - kw_only=True, default=Factory(lambda: DummyEmbeddingDriver()), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda: DummyEmbeddingDriver()), + metadata={"serializable": True}, ) vector_store_driver: BaseVectorStoreDriver = field( - default=Factory(lambda: DummyVectorStoreDriver()), kw_only=True, metadata={"serializable": True} + default=Factory(lambda: DummyVectorStoreDriver()), + kw_only=True, + metadata={"serializable": True}, ) conversation_memory_driver: Optional[BaseConversationMemoryDriver] = field( - default=None, kw_only=True, metadata={"serializable": True} + default=None, + kw_only=True, + metadata={"serializable": True}, ) text_to_speech_driver: BaseTextToSpeechDriver = field( - default=Factory(lambda: DummyTextToSpeechDriver()), kw_only=True, metadata={"serializable": True} + default=Factory(lambda: DummyTextToSpeechDriver()), + kw_only=True, + metadata={"serializable": True}, ) audio_transcription_driver: BaseAudioTranscriptionDriver = field( - default=Factory(lambda: DummyAudioTranscriptionDriver()), kw_only=True, metadata={"serializable": True} + default=Factory(lambda: DummyAudioTranscriptionDriver()), + kw_only=True, + metadata={"serializable": True}, ) diff --git a/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py b/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py index c2098bb67..9240c3a4f 100644 --- a/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py +++ b/griptape/drivers/audio_transcription/openai_audio_transcription_driver.py @@ -21,7 +21,7 @@ class OpenAiAudioTranscriptionDriver(BaseAudioTranscriptionDriver): default=Factory( lambda self: openai.OpenAI(api_key=self.api_key, base_url=self.base_url, organization=self.organization), takes_self=True, - ) + ), ) def try_run(self, audio: AudioArtifact, prompts: Optional[list[str]] = None) -> TextArtifact: diff --git a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py index 41fbf2a92..4e4f4aa31 100644 --- a/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_cohere_embedding_driver.py @@ -35,17 +35,22 @@ class AmazonBedrockCohereEmbeddingDriver(BaseEmbeddingDriver): input_type: str = field(default="search_query", kw_only=True) session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True + default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), + kw_only=True, ) bedrock_client: Any = field( - default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), kw_only=True + default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), + kw_only=True, ) def try_embed_chunk(self, chunk: str) -> list[float]: payload = {"input_type": self.input_type, "texts": [chunk]} response = self.bedrock_client.invoke_model( - body=json.dumps(payload), modelId=self.model, accept="*/*", contentType="application/json" + body=json.dumps(payload), + modelId=self.model, + accept="*/*", + contentType="application/json", ) response_body = json.loads(response.get("body").read()) diff --git a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py index 2eb83b033..5900d7d86 100644 --- a/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_bedrock_titan_embedding_driver.py @@ -31,17 +31,22 @@ class AmazonBedrockTitanEmbeddingDriver(BaseEmbeddingDriver): model: str = field(default=DEFAULT_MODEL, kw_only=True, metadata={"serializable": True}) session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True + default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), + kw_only=True, ) bedrock_client: Any = field( - default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), kw_only=True + default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), + kw_only=True, ) def try_embed_chunk(self, chunk: str) -> list[float]: payload = {"inputText": chunk} response = self.bedrock_client.invoke_model( - body=json.dumps(payload), modelId=self.model, accept="application/json", contentType="application/json" + body=json.dumps(payload), + modelId=self.model, + accept="application/json", + contentType="application/json", ) response_body = json.loads(response.get("body").read()) diff --git a/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py b/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py index 413ad2fe2..c4feb8a1d 100644 --- a/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py +++ b/griptape/drivers/embedding/amazon_sagemaker_jumpstart_embedding_driver.py @@ -16,7 +16,8 @@ class AmazonSageMakerJumpstartEmbeddingDriver(BaseEmbeddingDriver): session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) sagemaker_client: Any = field( - default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), kw_only=True + default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), + kw_only=True, ) endpoint: str = field(kw_only=True, metadata={"serializable": True}) custom_attributes: str = field(default="accept_eula=true", kw_only=True, metadata={"serializable": True}) diff --git a/griptape/drivers/embedding/azure_openai_embedding_driver.py b/griptape/drivers/embedding/azure_openai_embedding_driver.py index 420458e29..c1e601aef 100644 --- a/griptape/drivers/embedding/azure_openai_embedding_driver.py +++ b/griptape/drivers/embedding/azure_openai_embedding_driver.py @@ -24,16 +24,21 @@ class AzureOpenAiEmbeddingDriver(OpenAiEmbeddingDriver): """ azure_deployment: str = field( - kw_only=True, default=Factory(lambda self: self.model, takes_self=True), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda self: self.model, takes_self=True), + metadata={"serializable": True}, ) azure_endpoint: str = field(kw_only=True, metadata={"serializable": True}) azure_ad_token: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) azure_ad_token_provider: Optional[Callable[[], str]] = field( - kw_only=True, default=None, metadata={"serializable": False} + kw_only=True, + default=None, + metadata={"serializable": False}, ) api_version: str = field(default="2023-05-15", kw_only=True, metadata={"serializable": True}) tokenizer: OpenAiTokenizer = field( - default=Factory(lambda self: OpenAiTokenizer(model=self.model), takes_self=True), kw_only=True + default=Factory(lambda self: OpenAiTokenizer(model=self.model), takes_self=True), + kw_only=True, ) client: openai.AzureOpenAI = field( default=Factory( @@ -47,5 +52,5 @@ class AzureOpenAiEmbeddingDriver(OpenAiEmbeddingDriver): azure_ad_token_provider=self.azure_ad_token_provider, ), takes_self=True, - ) + ), ) diff --git a/griptape/drivers/embedding/huggingface_hub_embedding_driver.py b/griptape/drivers/embedding/huggingface_hub_embedding_driver.py index 9a8fd5292..c1be2ec96 100644 --- a/griptape/drivers/embedding/huggingface_hub_embedding_driver.py +++ b/griptape/drivers/embedding/huggingface_hub_embedding_driver.py @@ -25,7 +25,8 @@ class HuggingFaceHubEmbeddingDriver(BaseEmbeddingDriver): client: InferenceClient = field( default=Factory( lambda self: import_optional_dependency("huggingface_hub").InferenceClient( - model=self.model, token=self.api_token + model=self.model, + token=self.api_token, ), takes_self=True, ), diff --git a/griptape/drivers/embedding/openai_embedding_driver.py b/griptape/drivers/embedding/openai_embedding_driver.py index 73c737d6b..0995fba68 100644 --- a/griptape/drivers/embedding/openai_embedding_driver.py +++ b/griptape/drivers/embedding/openai_embedding_driver.py @@ -37,10 +37,11 @@ class OpenAiEmbeddingDriver(BaseEmbeddingDriver): default=Factory( lambda self: openai.OpenAI(api_key=self.api_key, base_url=self.base_url, organization=self.organization), takes_self=True, - ) + ), ) tokenizer: OpenAiTokenizer = field( - default=Factory(lambda self: OpenAiTokenizer(model=self.model), takes_self=True), kw_only=True + default=Factory(lambda self: OpenAiTokenizer(model=self.model), takes_self=True), + kw_only=True, ) def try_embed_chunk(self, chunk: str) -> list[float]: diff --git a/griptape/drivers/embedding/voyageai_embedding_driver.py b/griptape/drivers/embedding/voyageai_embedding_driver.py index b29dd5692..c5e418ed1 100644 --- a/griptape/drivers/embedding/voyageai_embedding_driver.py +++ b/griptape/drivers/embedding/voyageai_embedding_driver.py @@ -27,8 +27,9 @@ class VoyageAiEmbeddingDriver(BaseEmbeddingDriver): api_key: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) client: Any = field( default=Factory( - lambda self: import_optional_dependency("voyageai").Client(api_key=self.api_key), takes_self=True - ) + lambda self: import_optional_dependency("voyageai").Client(api_key=self.api_key), + takes_self=True, + ), ) tokenizer: VoyageAiTokenizer = field( default=Factory(lambda self: VoyageAiTokenizer(model=self.model, api_key=self.api_key), takes_self=True), diff --git a/griptape/drivers/event_listener/base_event_listener_driver.py b/griptape/drivers/event_listener/base_event_listener_driver.py index 710e6382f..7792943f3 100644 --- a/griptape/drivers/event_listener/base_event_listener_driver.py +++ b/griptape/drivers/event_listener/base_event_listener_driver.py @@ -16,7 +16,8 @@ @define class BaseEventListenerDriver(ABC): futures_executor_fn: Callable[[], futures.Executor] = field( - default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), + kw_only=True, ) batched: bool = field(default=True, kw_only=True) batch_size: int = field(default=10, kw_only=True) diff --git a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py index e89ab6da0..1520afbcc 100644 --- a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py +++ b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py @@ -21,11 +21,13 @@ class GriptapeCloudEventListenerDriver(BaseEventListenerDriver): """ base_url: str = field( - default=Factory(lambda: os.getenv("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")), kw_only=True + default=Factory(lambda: os.getenv("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")), + kw_only=True, ) api_key: str = field(kw_only=True) headers: dict = field( - default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True + default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), + kw_only=True, ) structure_run_id: str = field(default=Factory(lambda: os.getenv("GT_CLOUD_STRUCTURE_RUN_ID")), kw_only=True) @@ -33,7 +35,7 @@ class GriptapeCloudEventListenerDriver(BaseEventListenerDriver): def validate_run_id(self, _, structure_run_id: str): if structure_run_id is None: raise ValueError( - "structure_run_id must be set either in the constructor or as an environment variable (GT_CLOUD_STRUCTURE_RUN_ID)." + "structure_run_id must be set either in the constructor or as an environment variable (GT_CLOUD_STRUCTURE_RUN_ID).", ) def try_publish_event_payload(self, event_payload: dict) -> None: diff --git a/griptape/drivers/event_listener/pusher_event_listener_driver.py b/griptape/drivers/event_listener/pusher_event_listener_driver.py index 2e9de8d72..ce9a4fb34 100644 --- a/griptape/drivers/event_listener/pusher_event_listener_driver.py +++ b/griptape/drivers/event_listener/pusher_event_listener_driver.py @@ -22,7 +22,11 @@ class PusherEventListenerDriver(BaseEventListenerDriver): pusher_client: Pusher = field( default=Factory( lambda self: import_optional_dependency("pusher").Pusher( - app_id=self.app_id, key=self.key, secret=self.secret, cluster=self.cluster, ssl=True + app_id=self.app_id, + key=self.key, + secret=self.secret, + cluster=self.cluster, + ssl=True, ), takes_self=True, ), diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index 84e49ecd3..18b591b41 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -94,7 +94,10 @@ def _list_files_and_dirs(self, full_key: str, **kwargs) -> list[str]: paginator = self.s3_client.get_paginator("list_objects_v2") pages = paginator.paginate( - Bucket=self.bucket, Prefix=full_key, Delimiter="/", PaginationConfig=pagination_config + Bucket=self.bucket, + Prefix=full_key, + Delimiter="/", + PaginationConfig=pagination_config, ) files_and_dirs = [] for page in pages: diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index b69aa374d..5fdb84b8f 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -35,7 +35,7 @@ class BaseFileManagerDriver(ABC): "gif": loaders.ImageLoader(), "bmp": loaders.ImageLoader(), "tiff": loaders.ImageLoader(), - } + }, ), kw_only=True, ) diff --git a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py index a8f4c2d2e..7106c8192 100644 --- a/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py +++ b/griptape/drivers/image_generation/amazon_bedrock_image_generation_driver.py @@ -28,7 +28,7 @@ class AmazonBedrockImageGenerationDriver(BaseMultiModelImageGenerationDriver): session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) bedrock_client: Any = field( - default=Factory(lambda self: self.session.client(service_name="bedrock-runtime"), takes_self=True) + default=Factory(lambda self: self.session.client(service_name="bedrock-runtime"), takes_self=True), ) image_width: int = field(default=512, kw_only=True, metadata={"serializable": True}) image_height: int = field(default=512, kw_only=True, metadata={"serializable": True}) @@ -36,7 +36,11 @@ class AmazonBedrockImageGenerationDriver(BaseMultiModelImageGenerationDriver): def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[str]] = None) -> ImageArtifact: request = self.image_generation_model_driver.text_to_image_request_parameters( - prompts, self.image_width, self.image_height, negative_prompts=negative_prompts, seed=self.seed + prompts, + self.image_width, + self.image_height, + negative_prompts=negative_prompts, + seed=self.seed, ) image_bytes = self._make_request(request) @@ -51,10 +55,16 @@ def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[ ) def try_image_variation( - self, prompts: list[str], image: ImageArtifact, negative_prompts: Optional[list[str]] = None + self, + prompts: list[str], + image: ImageArtifact, + negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: request = self.image_generation_model_driver.image_variation_request_parameters( - prompts, image=image, negative_prompts=negative_prompts, seed=self.seed + prompts, + image=image, + negative_prompts=negative_prompts, + seed=self.seed, ) image_bytes = self._make_request(request) @@ -76,7 +86,11 @@ def try_image_inpainting( negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: request = self.image_generation_model_driver.image_inpainting_request_parameters( - prompts, image=image, mask=mask, negative_prompts=negative_prompts, seed=self.seed + prompts, + image=image, + mask=mask, + negative_prompts=negative_prompts, + seed=self.seed, ) image_bytes = self._make_request(request) @@ -98,7 +112,11 @@ def try_image_outpainting( negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: request = self.image_generation_model_driver.image_outpainting_request_parameters( - prompts, image=image, mask=mask, negative_prompts=negative_prompts, seed=self.seed + prompts, + image=image, + mask=mask, + negative_prompts=negative_prompts, + seed=self.seed, ) image_bytes = self._make_request(request) @@ -114,7 +132,10 @@ def try_image_outpainting( def _make_request(self, request: dict) -> bytes: response = self.bedrock_client.invoke_model( - body=json.dumps(request), modelId=self.model, accept="application/json", contentType="application/json" + body=json.dumps(request), + modelId=self.model, + accept="application/json", + contentType="application/json", ) response_body = json.loads(response.get("body").read()) diff --git a/griptape/drivers/image_generation/azure_openai_image_generation_driver.py b/griptape/drivers/image_generation/azure_openai_image_generation_driver.py index d7ec7681a..85facda4c 100644 --- a/griptape/drivers/image_generation/azure_openai_image_generation_driver.py +++ b/griptape/drivers/image_generation/azure_openai_image_generation_driver.py @@ -22,12 +22,16 @@ class AzureOpenAiImageGenerationDriver(OpenAiImageGenerationDriver): """ azure_deployment: str = field( - kw_only=True, default=Factory(lambda self: self.model, takes_self=True), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda self: self.model, takes_self=True), + metadata={"serializable": True}, ) azure_endpoint: str = field(kw_only=True, metadata={"serializable": True}) azure_ad_token: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) azure_ad_token_provider: Optional[Callable[[], str]] = field( - kw_only=True, default=None, metadata={"serializable": False} + kw_only=True, + default=None, + metadata={"serializable": False}, ) api_version: str = field(default="2024-02-01", kw_only=True, metadata={"serializable": True}) client: openai.AzureOpenAI = field( @@ -42,5 +46,5 @@ class AzureOpenAiImageGenerationDriver(OpenAiImageGenerationDriver): azure_ad_token_provider=self.azure_ad_token_provider, ), takes_self=True, - ) + ), ) diff --git a/griptape/drivers/image_generation/base_image_generation_driver.py b/griptape/drivers/image_generation/base_image_generation_driver.py index ee132605c..93666a513 100644 --- a/griptape/drivers/image_generation/base_image_generation_driver.py +++ b/griptape/drivers/image_generation/base_image_generation_driver.py @@ -39,7 +39,10 @@ def run_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[ raise Exception("Failed to run text to image generation") def run_image_variation( - self, prompts: list[str], image: ImageArtifact, negative_prompts: Optional[list[str]] = None + self, + prompts: list[str], + image: ImageArtifact, + negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: for attempt in self.retrying(): with attempt: @@ -93,7 +96,10 @@ def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[ @abstractmethod def try_image_variation( - self, prompts: list[str], image: ImageArtifact, negative_prompts: Optional[list[str]] = None + self, + prompts: list[str], + image: ImageArtifact, + negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: ... @abstractmethod diff --git a/griptape/drivers/image_generation/dummy_image_generation_driver.py b/griptape/drivers/image_generation/dummy_image_generation_driver.py index 788280a11..9d668c5b2 100644 --- a/griptape/drivers/image_generation/dummy_image_generation_driver.py +++ b/griptape/drivers/image_generation/dummy_image_generation_driver.py @@ -19,7 +19,10 @@ def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[ raise DummyException(__class__.__name__, "try_text_to_image") def try_image_variation( - self, prompts: list[str], image: ImageArtifact, negative_prompts: Optional[list[str]] = None + self, + prompts: list[str], + image: ImageArtifact, + negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: raise DummyException(__class__.__name__, "try_image_variation") diff --git a/griptape/drivers/image_generation/leonardo_image_generation_driver.py b/griptape/drivers/image_generation/leonardo_image_generation_driver.py index 6b6cdc61f..e32dbb4c7 100644 --- a/griptape/drivers/image_generation/leonardo_image_generation_driver.py +++ b/griptape/drivers/image_generation/leonardo_image_generation_driver.py @@ -42,7 +42,9 @@ class LeonardoImageGenerationDriver(BaseImageGenerationDriver): init_strength: Optional[float] = field(default=None, kw_only=True, metadata={"serializable": True}) control_net: bool = field(default=False, kw_only=True, metadata={"serializable": True}) control_net_type: Optional[Literal["POSE", "CANNY", "DEPTH"]] = field( - default=None, kw_only=True, metadata={"serializable": True} + default=None, + kw_only=True, + metadata={"serializable": True}, ) def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[str]] = None) -> ImageArtifact: @@ -63,14 +65,19 @@ def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[ ) def try_image_variation( - self, prompts: list[str], image: ImageArtifact, negative_prompts: Optional[list[str]] = None + self, + prompts: list[str], + image: ImageArtifact, + negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: if negative_prompts is None: negative_prompts = [] init_image_id = self._upload_init_image(image) generation_id = self._create_generation( - prompts=prompts, negative_prompts=negative_prompts, init_image_id=init_image_id + prompts=prompts, + negative_prompts=negative_prompts, + init_image_id=init_image_id, ) image_url = self._get_image_url(generation_id=generation_id) image_data = self._download_image(url=image_url) @@ -121,7 +128,10 @@ def _upload_init_image(self, image: ImageArtifact) -> str: return init_image_id def _create_generation( - self, prompts: list[str], negative_prompts: list[str], init_image_id: Optional[str] = None + self, + prompts: list[str], + negative_prompts: list[str], + init_image_id: Optional[str] = None, ) -> str: prompt = ", ".join(prompts) negative_prompt = ", ".join(negative_prompts) @@ -169,7 +179,8 @@ def _make_api_request(self, endpoint: str, request: dict, method: str = "POST") def _get_image_url(self, generation_id: str) -> str: for attempt in range(self.max_attempts): response = self.requests_session.get( - url=f"{self.api_base}/generations/{generation_id}", headers={"Authorization": f"Bearer {self.api_key}"} + url=f"{self.api_base}/generations/{generation_id}", + headers={"Authorization": f"Bearer {self.api_key}"}, ).json() if response["generations_by_pk"]["status"] == "PENDING": diff --git a/griptape/drivers/image_generation/openai_image_generation_driver.py b/griptape/drivers/image_generation/openai_image_generation_driver.py index d3e8ce727..54eab48ec 100644 --- a/griptape/drivers/image_generation/openai_image_generation_driver.py +++ b/griptape/drivers/image_generation/openai_image_generation_driver.py @@ -42,14 +42,20 @@ class OpenAiImageGenerationDriver(BaseImageGenerationDriver): default=Factory( lambda self: openai.OpenAI(api_key=self.api_key, base_url=self.base_url, organization=self.organization), takes_self=True, - ) + ), ) style: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) quality: Union[Literal["standard"], Literal["hd"]] = field( - default="standard", kw_only=True, metadata={"serializable": True} + default="standard", + kw_only=True, + metadata={"serializable": True}, ) image_size: Union[ - Literal["256x256"], Literal["512x512"], Literal["1024x1024"], Literal["1024x1792"], Literal["1792x1024"] + Literal["256x256"], + Literal["512x512"], + Literal["1024x1024"], + Literal["1024x1792"], + Literal["1792x1024"], ] = field(default="1024x1024", kw_only=True, metadata={"serializable": True}) response_format: Literal["b64_json"] = field(default="b64_json", kw_only=True, metadata={"serializable": True}) @@ -76,12 +82,18 @@ def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[ return self._parse_image_response(response, prompt) def try_image_variation( - self, prompts: list[str], image: ImageArtifact, negative_prompts: Optional[list[str]] = None + self, + prompts: list[str], + image: ImageArtifact, + negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: image_size = self._dall_e_2_filter_image_size("variation") response = self.client.images.create_variation( - image=image.value, n=1, response_format=self.response_format, size=image_size + image=image.value, + n=1, + response_format=self.response_format, + size=image_size, ) return self._parse_image_response(response, "") @@ -97,7 +109,11 @@ def try_image_inpainting( prompt = ", ".join(prompts) response = self.client.images.edit( - prompt=prompt, image=image.value, mask=mask.value, response_format=self.response_format, size=image_size + prompt=prompt, + image=image.value, + mask=mask.value, + response_format=self.response_format, + size=image_size, ) return self._parse_image_response(response, prompt) diff --git a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py index 78bcecc87..92428e157 100644 --- a/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py +++ b/griptape/drivers/image_generation_model/bedrock_stable_diffusion_image_generation_model_driver.py @@ -46,7 +46,11 @@ def text_to_image_request_parameters( seed: Optional[int] = None, ) -> dict: return self._request_parameters( - prompts, width=image_width, height=image_height, negative_prompts=negative_prompts, seed=seed + prompts, + width=image_width, + height=image_height, + negative_prompts=negative_prompts, + seed=seed, ) def image_variation_request_parameters( diff --git a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py index cc1d13f4e..46406d972 100644 --- a/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py +++ b/griptape/drivers/image_query/amazon_bedrock_image_query_driver.py @@ -18,14 +18,18 @@ class AmazonBedrockImageQueryDriver(BaseMultiModelImageQueryDriver): session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) bedrock_client: Any = field( - default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), kw_only=True + default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), + kw_only=True, ) def try_query(self, query: str, images: list[ImageArtifact]) -> TextArtifact: payload = self.image_query_model_driver.image_query_request_parameters(query, images, self.max_tokens) response = self.bedrock_client.invoke_model( - modelId=self.model, contentType="application/json", accept="application/json", body=json.dumps(payload) + modelId=self.model, + contentType="application/json", + accept="application/json", + body=json.dumps(payload), ) response_body = json.loads(response.get("body").read()) diff --git a/griptape/drivers/image_query/anthropic_image_query_driver.py b/griptape/drivers/image_query/anthropic_image_query_driver.py index fe39177ab..c4756783e 100644 --- a/griptape/drivers/image_query/anthropic_image_query_driver.py +++ b/griptape/drivers/image_query/anthropic_image_query_driver.py @@ -23,7 +23,8 @@ class AnthropicImageQueryDriver(BaseImageQueryDriver): model: str = field(kw_only=True, metadata={"serializable": True}) client: Any = field( default=Factory( - lambda self: import_optional_dependency("anthropic").Anthropic(api_key=self.api_key), takes_self=True + lambda self: import_optional_dependency("anthropic").Anthropic(api_key=self.api_key), + takes_self=True, ), kw_only=True, ) diff --git a/griptape/drivers/image_query/azure_openai_image_query_driver.py b/griptape/drivers/image_query/azure_openai_image_query_driver.py index ad37737c7..04492e471 100644 --- a/griptape/drivers/image_query/azure_openai_image_query_driver.py +++ b/griptape/drivers/image_query/azure_openai_image_query_driver.py @@ -22,12 +22,16 @@ class AzureOpenAiImageQueryDriver(OpenAiImageQueryDriver): """ azure_deployment: str = field( - kw_only=True, default=Factory(lambda self: self.model, takes_self=True), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda self: self.model, takes_self=True), + metadata={"serializable": True}, ) azure_endpoint: str = field(kw_only=True, metadata={"serializable": True}) azure_ad_token: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) azure_ad_token_provider: Optional[Callable[[], str]] = field( - kw_only=True, default=None, metadata={"serializable": False} + kw_only=True, + default=None, + metadata={"serializable": False}, ) api_version: str = field(default="2024-02-01", kw_only=True, metadata={"serializable": True}) client: openai.AzureOpenAI = field( @@ -42,5 +46,5 @@ class AzureOpenAiImageQueryDriver(OpenAiImageQueryDriver): azure_ad_token_provider=self.azure_ad_token_provider, ), takes_self=True, - ) + ), ) diff --git a/griptape/drivers/image_query/base_image_query_driver.py b/griptape/drivers/image_query/base_image_query_driver.py index 3f606e749..88fbb5160 100644 --- a/griptape/drivers/image_query/base_image_query_driver.py +++ b/griptape/drivers/image_query/base_image_query_driver.py @@ -21,7 +21,7 @@ class BaseImageQueryDriver(SerializableMixin, ExponentialBackoffMixin, ABC): def before_run(self, query: str, images: list[ImageArtifact]) -> None: if self.structure: self.structure.publish_event( - StartImageQueryEvent(query=query, images_info=[image.to_text() for image in images]) + StartImageQueryEvent(query=query, images_info=[image.to_text() for image in images]), ) def after_run(self, result: str) -> None: diff --git a/griptape/drivers/image_query/openai_image_query_driver.py b/griptape/drivers/image_query/openai_image_query_driver.py index 693f67184..b607c97f5 100644 --- a/griptape/drivers/image_query/openai_image_query_driver.py +++ b/griptape/drivers/image_query/openai_image_query_driver.py @@ -28,12 +28,12 @@ class OpenAiImageQueryDriver(BaseImageQueryDriver): default=Factory( lambda self: openai.OpenAI(api_key=self.api_key, base_url=self.base_url, organization=self.organization), takes_self=True, - ) + ), ) def try_query(self, query: str, images: list[ImageArtifact]) -> TextArtifact: message_parts: list[ChatCompletionContentPartParam] = [ - ChatCompletionContentPartTextParam(type="text", text=query) + ChatCompletionContentPartTextParam(type="text", text=query), ] for image in images: @@ -41,7 +41,7 @@ def try_query(self, query: str, images: list[ImageArtifact]) -> TextArtifact: ChatCompletionContentPartImageParam( type="image_url", image_url={"url": f"data:{image.mime_type};base64,{image.base64}", "detail": self.image_quality}, - ) + ), ) messages = ChatCompletionUserMessageParam(content=message_parts, role="user") diff --git a/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py b/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py index 531b009af..2ba3737e8 100644 --- a/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py +++ b/griptape/drivers/memory/conversation/redis_conversation_memory_driver.py @@ -40,10 +40,14 @@ class RedisConversationMemoryDriver(BaseConversationMemoryDriver): client: Redis = field( default=Factory( lambda self: import_optional_dependency("redis").Redis( - host=self.host, port=self.port, db=self.db, password=self.password, decode_responses=False + host=self.host, + port=self.port, + db=self.db, + password=self.password, + decode_responses=False, ), takes_self=True, - ) + ), ) def store(self, memory: BaseConversationMemory) -> None: diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 824e3abcc..4cb5801d3 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -44,11 +44,13 @@ class AmazonBedrockPromptDriver(BasePromptDriver): session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) bedrock_client: Any = field( - default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), kw_only=True + default=Factory(lambda self: self.session.client("bedrock-runtime"), takes_self=True), + kw_only=True, ) additional_model_request_fields: dict = field(default=Factory(dict), kw_only=True) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), kw_only=True + default=Factory(lambda self: AmazonBedrockTokenizer(model=self.model), takes_self=True), + kw_only=True, ) use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) tool_choice: dict = field(default=Factory(lambda: {"auto": {}}), kw_only=True, metadata={"serializable": True}) @@ -76,7 +78,10 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: elif "metadata" in event: usage = event["metadata"]["usage"] yield DeltaMessage( - usage=DeltaMessage.Usage(input_tokens=usage["inputTokens"], output_tokens=usage["outputTokens"]) + usage=DeltaMessage.Usage( + input_tokens=usage["inputTokens"], + output_tokens=usage["outputTokens"], + ), ) else: raise Exception("model response is empty") @@ -122,10 +127,10 @@ def __to_bedrock_tools(self, tools: list[BaseTool]) -> list[dict]: "description": tool.activity_description(activity), "inputSchema": { "json": (tool.activity_schema(activity) or Schema({})).json_schema( - "http://json-schema.org/draft-07/schema#" - ) + "http://json-schema.org/draft-07/schema#", + ), }, - } + }, } for tool in tools for activity in tool.activities() @@ -146,7 +151,7 @@ def __to_bedrock_message_content(self, content: BaseMessageContent) -> dict: "toolUseId": action_call.tag, "name": f"{action_call.name}_{action_call.path}", "input": action_call.input, - } + }, } elif isinstance(content, ActionResultMessageContent): artifact = content.artifact @@ -161,7 +166,7 @@ def __to_bedrock_message_content(self, content: BaseMessageContent) -> dict: "toolUseId": content.action.tag, "content": message_content, "status": "error" if isinstance(artifact, ErrorArtifact) else "success", - } + }, } else: raise ValueError(f"Unsupported content type: {type(content)}") @@ -182,9 +187,12 @@ def __to_prompt_stack_message_content(self, content: dict) -> BaseMessageContent return ActionCallMessageContent( artifact=ActionArtifact( value=ToolAction( - tag=content["toolUse"]["toolUseId"], name=name, path=path, input=content["toolUse"]["input"] - ) - ) + tag=content["toolUse"]["toolUseId"], + name=name, + path=path, + input=content["toolUse"]["input"], + ), + ), ) else: raise ValueError(f"Unsupported message content type: {content}") @@ -204,7 +212,8 @@ def __to_prompt_stack_delta_message_content(self, event: dict) -> BaseDeltaMessa ) elif "text" in content_block: return TextDeltaMessageContent( - content_block["text"], index=event["contentBlockStart"]["contentBlockIndex"] + content_block["text"], + index=event["contentBlockStart"]["contentBlockIndex"], ) else: raise ValueError(f"Unsupported message content type: {event}") @@ -213,7 +222,8 @@ def __to_prompt_stack_delta_message_content(self, event: dict) -> BaseDeltaMessa if "text" in content_block_delta["delta"]: return TextDeltaMessageContent( - content_block_delta["delta"]["text"], index=content_block_delta["contentBlockIndex"] + content_block_delta["delta"]["text"], + index=content_block_delta["contentBlockIndex"], ) elif "toolUse" in content_block_delta["delta"]: return ActionCallDeltaMessageContent( diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 6bc83954e..70862f55f 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -23,7 +23,8 @@ class AmazonSageMakerJumpstartPromptDriver(BasePromptDriver): session: boto3.Session = field(default=Factory(lambda: import_optional_dependency("boto3").Session()), kw_only=True) sagemaker_client: Any = field( - default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), kw_only=True + default=Factory(lambda self: self.session.client("sagemaker-runtime"), takes_self=True), + kw_only=True, ) endpoint: str = field(kw_only=True, metadata={"serializable": True}) custom_attributes: str = field(default="accept_eula=true", kw_only=True, metadata={"serializable": True}) @@ -32,7 +33,8 @@ class AmazonSageMakerJumpstartPromptDriver(BasePromptDriver): max_tokens: int = field(default=250, kw_only=True, metadata={"serializable": True}) tokenizer: HuggingFaceTokenizer = field( default=Factory( - lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), takes_self=True + lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), + takes_self=True, ), kw_only=True, ) diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 9eed9c275..14be9a26b 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -55,12 +55,14 @@ class AnthropicPromptDriver(BasePromptDriver): model: str = field(kw_only=True, metadata={"serializable": True}) client: Client = field( default=Factory( - lambda self: import_optional_dependency("anthropic").Anthropic(api_key=self.api_key), takes_self=True + lambda self: import_optional_dependency("anthropic").Anthropic(api_key=self.api_key), + takes_self=True, ), kw_only=True, ) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: AnthropicTokenizer(model=self.model), takes_self=True), kw_only=True + default=Factory(lambda self: AnthropicTokenizer(model=self.model), takes_self=True), + kw_only=True, ) top_p: float = field(default=0.999, kw_only=True, metadata={"serializable": True}) top_k: int = field(default=250, kw_only=True, metadata={"serializable": True}) @@ -189,14 +191,15 @@ def __to_prompt_stack_message_content(self, content: ContentBlock) -> BaseMessag return ActionCallMessageContent( artifact=ActionArtifact( - value=ToolAction(tag=content.id, name=name, path=path, input=content.input) # pyright: ignore[reportArgumentType] - ) + value=ToolAction(tag=content.id, name=name, path=path, input=content.input), # pyright: ignore[reportArgumentType] + ), ) else: raise ValueError(f"Unsupported message content type: {content.type}") def __to_prompt_stack_delta_message_content( - self, event: ContentBlockDeltaEvent | ContentBlockStartEvent + self, + event: ContentBlockDeltaEvent | ContentBlockStartEvent, ) -> BaseDeltaMessageContent: if event.type == "content_block_start": content_block = event.content_block diff --git a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py index dca64763b..b08b51b69 100644 --- a/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/azure_openai_chat_prompt_driver.py @@ -25,12 +25,16 @@ class AzureOpenAiChatPromptDriver(OpenAiChatPromptDriver): """ azure_deployment: str = field( - kw_only=True, default=Factory(lambda self: self.model, takes_self=True), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda self: self.model, takes_self=True), + metadata={"serializable": True}, ) azure_endpoint: str = field(kw_only=True, metadata={"serializable": True}) azure_ad_token: Optional[str] = field(kw_only=True, default=None, metadata={"serializable": False}) azure_ad_token_provider: Optional[Callable[[], str]] = field( - kw_only=True, default=None, metadata={"serializable": False} + kw_only=True, + default=None, + metadata={"serializable": False}, ) api_version: str = field(default="2023-05-15", kw_only=True, metadata={"serializable": True}) client: openai.AzureOpenAI = field( @@ -45,7 +49,7 @@ class AzureOpenAiChatPromptDriver(OpenAiChatPromptDriver): azure_ad_token_provider=self.azure_ad_token_provider, ), takes_self=True, - ) + ), ) def _base_params(self, prompt_stack: PromptStack) -> dict: diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 3f957c34e..57cb7272d 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -62,7 +62,7 @@ def after_run(self, result: Message) -> None: result=result.value, input_token_count=result.usage.input_tokens, output_token_count=result.usage.output_tokens, - ) + ), ) def run(self, prompt_stack: PromptStack) -> Message: diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index d44016d19..0a28a9c59 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -45,10 +45,10 @@ class CoherePromptDriver(BasePromptDriver): api_key: str = field(metadata={"serializable": False}) model: str = field(metadata={"serializable": True}) client: Client = field( - default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True) + default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True), ) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True) + default=Factory(lambda self: CohereTokenizer(model=self.model, client=self.client), takes_self=True), ) force_single_step: bool = field(default=False, kw_only=True, metadata={"serializable": True}) use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) @@ -71,7 +71,7 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: usage = event.response.meta.tokens yield DeltaMessage( - usage=DeltaMessage.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens) + usage=DeltaMessage.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens), ) elif event.event_type == "text-generation" or event.event_type == "tool-calls-chunk": yield DeltaMessage(content=self.__to_prompt_stack_delta_message_content(event)) @@ -91,7 +91,7 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: # History messages history_messages = self.__to_cohere_messages( - [message for message in prompt_stack.messages[:-1] if not message.is_system()] + [message for message in prompt_stack.messages[:-1] if not message.is_system()], ) # System message (preamble) @@ -198,7 +198,7 @@ def __to_cohere_tools(self, tools: list[BaseTool]) -> list[dict]: } for property_name, property_value in properties.items() }, - } + }, ) return tool_definitions @@ -217,11 +217,11 @@ def __to_prompt_stack_message_content(self, response: NonStreamedChatResponse) - name=ToolAction.from_native_tool_name(tool_call.name)[0], path=ToolAction.from_native_tool_name(tool_call.name)[1], input=tool_call.parameters, - ) - ) + ), + ), ) for tool_call in response.tool_calls - ] + ], ) return content diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index ed85f6229..33c5a9985 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -50,7 +50,8 @@ class GooglePromptDriver(BasePromptDriver): api_key: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) model: str = field(kw_only=True, metadata={"serializable": True}) model_client: GenerativeModel = field( - default=Factory(lambda self: self._default_model_client(), takes_self=True), kw_only=True + default=Factory(lambda self: self._default_model_client(), takes_self=True), + kw_only=True, ) tokenizer: BaseTokenizer = field( default=Factory(lambda self: GoogleTokenizer(api_key=self.api_key, model=self.model), takes_self=True), @@ -64,7 +65,8 @@ class GooglePromptDriver(BasePromptDriver): def try_run(self, prompt_stack: PromptStack) -> Message: messages = self.__to_google_messages(prompt_stack) response: GenerateContentResponse = self.model_client.generate_content( - messages, **self._base_params(prompt_stack) + messages, + **self._base_params(prompt_stack), ) usage_metadata = response.usage_metadata @@ -73,14 +75,17 @@ def try_run(self, prompt_stack: PromptStack) -> Message: content=[self.__to_prompt_stack_message_content(part) for part in response.parts], role=Message.ASSISTANT_ROLE, usage=Message.Usage( - input_tokens=usage_metadata.prompt_token_count, output_tokens=usage_metadata.candidates_token_count + input_tokens=usage_metadata.prompt_token_count, + output_tokens=usage_metadata.candidates_token_count, ), ) def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: messages = self.__to_google_messages(prompt_stack) response: GenerateContentResponse = self.model_client.generate_content( - messages, **self._base_params(prompt_stack), stream=True + messages, + **self._base_params(prompt_stack), + stream=True, ) prompt_token_count = None @@ -100,7 +105,8 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: ) else: yield DeltaMessage( - content=content, usage=DeltaMessage.Usage(output_tokens=usage_metadata.candidates_token_count) + content=content, + usage=DeltaMessage.Usage(output_tokens=usage_metadata.candidates_token_count), ) def _base_params(self, prompt_stack: PromptStack) -> dict: @@ -111,7 +117,8 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: system_messages = prompt_stack.system_messages if system_messages: self.model_client._system_instruction = ContentDict( - role="system", parts=[Part(text=system_message.to_text()) for system_message in system_messages] + role="system", + parts=[Part(text=system_message.to_text()) for system_message in system_messages], ) return { @@ -124,7 +131,7 @@ def _base_params(self, prompt_stack: PromptStack) -> dict: "temperature": self.temperature, "top_p": self.top_p, "top_k": self.top_k, - } + }, ), **( { @@ -150,7 +157,7 @@ def __to_google_messages(self, prompt_stack: PromptStack) -> ContentsType: { "role": self.__to_google_role(message), "parts": [self.__to_google_message_content(content) for content in message.content], - } + }, ) for message in prompt_stack.messages if not message.is_system() @@ -207,8 +214,9 @@ def __to_google_message_content(self, content: BaseMessageContent) -> ContentDic return protos.Part( function_response=protos.FunctionResponse( - name=content.action.to_native_tool_name(), response=artifact.to_dict() - ) + name=content.action.to_native_tool_name(), + response=artifact.to_dict(), + ), ) else: @@ -224,7 +232,7 @@ def __to_prompt_stack_message_content(self, content: Part) -> BaseMessageContent args = {k: v for k, v in function_call.args.items()} return ActionCallMessageContent( - artifact=ActionArtifact(value=ToolAction(tag=function_call.name, name=name, path=path, input=args)) + artifact=ActionArtifact(value=ToolAction(tag=function_call.name, name=name, path=path, input=args)), ) else: raise ValueError(f"Unsupported message content type {content}") @@ -239,7 +247,10 @@ def __to_prompt_stack_delta_message_content(self, content: Part) -> BaseDeltaMes args = {k: v for k, v in function_call.args.items()} return ActionCallDeltaMessageContent( - tag=function_call.name, name=name, path=path, partial_input=json.dumps(args) + tag=function_call.name, + name=name, + path=path, + partial_input=json.dumps(args), ) else: raise ValueError(f"Unsupported message content type {content}") diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index 7d1debbf7..072b01ab5 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -35,7 +35,8 @@ class HuggingFaceHubPromptDriver(BasePromptDriver): client: InferenceClient = field( default=Factory( lambda self: import_optional_dependency("huggingface_hub").InferenceClient( - model=self.model, token=self.api_token + model=self.model, + token=self.api_token, ), takes_self=True, ), @@ -43,7 +44,8 @@ class HuggingFaceHubPromptDriver(BasePromptDriver): ) tokenizer: HuggingFaceTokenizer = field( default=Factory( - lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), takes_self=True + lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), + takes_self=True, ), kw_only=True, ) @@ -52,7 +54,10 @@ def try_run(self, prompt_stack: PromptStack) -> Message: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( - prompt, return_full_text=False, max_new_tokens=self.max_tokens, **self.params + prompt, + return_full_text=False, + max_new_tokens=self.max_tokens, + **self.params, ) input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) output_tokens = len(self.tokenizer.tokenizer.encode(response)) @@ -67,7 +72,11 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: prompt = self.prompt_stack_to_string(prompt_stack) response = self.client.text_generation( - prompt, return_full_text=False, max_new_tokens=self.max_tokens, stream=True, **self.params + prompt, + return_full_text=False, + max_new_tokens=self.max_tokens, + stream=True, + **self.params, ) input_tokens = len(self.__prompt_stack_to_tokens(prompt_stack)) diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index caff742c3..992aff918 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -30,24 +30,32 @@ class HuggingFacePipelinePromptDriver(BasePromptDriver): params: dict = field(factory=dict, kw_only=True, metadata={"serializable": True}) tokenizer: HuggingFaceTokenizer = field( default=Factory( - lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), takes_self=True + lambda self: HuggingFaceTokenizer(model=self.model, max_output_tokens=self.max_tokens), + takes_self=True, ), kw_only=True, ) pipe: TextGenerationPipeline = field( default=Factory( lambda self: import_optional_dependency("transformers").pipeline( - "text-generation", model=self.model, max_new_tokens=self.max_tokens, tokenizer=self.tokenizer.tokenizer + "text-generation", + model=self.model, + max_new_tokens=self.max_tokens, + tokenizer=self.tokenizer.tokenizer, ), takes_self=True, - ) + ), ) def try_run(self, prompt_stack: PromptStack) -> Message: messages = self._prompt_stack_to_messages(prompt_stack) result = self.pipe( - messages, max_new_tokens=self.max_tokens, temperature=self.temperature, do_sample=True, **self.params + messages, + max_new_tokens=self.max_tokens, + temperature=self.temperature, + do_sample=True, + **self.params, ) if isinstance(result, list): diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py index 040099070..fb1e28e87 100644 --- a/griptape/drivers/prompt/ollama_prompt_driver.py +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -41,7 +41,9 @@ class OllamaPromptDriver(BasePromptDriver): tokenizer: BaseTokenizer = field( default=Factory( lambda self: SimpleTokenizer( - characters_per_token=4, max_input_tokens=2000, max_output_tokens=self.max_tokens + characters_per_token=4, + max_input_tokens=2000, + max_output_tokens=self.max_tokens, ), takes_self=True, ), @@ -95,7 +97,7 @@ def _prompt_stack_to_messages(self, prompt_stack: PromptStack) -> list[dict]: content.artifact.base64 for content in message.content if isinstance(content, ImageMessageContent) - ] + ], } if any(isinstance(content, ImageMessageContent) for content in message.content) else {} diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index f5b3796ed..9c4ab9a74 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -58,15 +58,18 @@ class OpenAiChatPromptDriver(BasePromptDriver): default=Factory( lambda self: openai.OpenAI(api_key=self.api_key, base_url=self.base_url, organization=self.organization), takes_self=True, - ) + ), ) model: str = field(kw_only=True, metadata={"serializable": True}) tokenizer: BaseTokenizer = field( - default=Factory(lambda self: OpenAiTokenizer(model=self.model), takes_self=True), kw_only=True + default=Factory(lambda self: OpenAiTokenizer(model=self.model), takes_self=True), + kw_only=True, ) user: str = field(default="", kw_only=True, metadata={"serializable": True}) response_format: Optional[Literal["json_object"]] = field( - default=None, kw_only=True, metadata={"serializable": True} + default=None, + kw_only=True, + metadata={"serializable": True}, ) seed: Optional[int] = field(default=None, kw_only=True, metadata={"serializable": True}) tool_choice: str = field(default="auto", kw_only=True, metadata={"serializable": False}) @@ -80,7 +83,7 @@ class OpenAiChatPromptDriver(BasePromptDriver): openai.NotFoundError, openai.ConflictError, openai.UnprocessableEntityError, - ) + ), ), kw_only=True, ) @@ -95,7 +98,8 @@ def try_run(self, prompt_stack: PromptStack) -> Message: content=self.__to_prompt_stack_message_content(message), role=Message.ASSISTANT_ROLE, usage=Message.Usage( - input_tokens=result.usage.prompt_tokens, output_tokens=result.usage.completion_tokens + input_tokens=result.usage.prompt_tokens, + output_tokens=result.usage.completion_tokens, ), ) else: @@ -108,8 +112,9 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: if chunk.usage is not None: yield DeltaMessage( usage=DeltaMessage.Usage( - input_tokens=chunk.usage.prompt_tokens, output_tokens=chunk.usage.completion_tokens - ) + input_tokens=chunk.usage.prompt_tokens, + output_tokens=chunk.usage.completion_tokens, + ), ) elif chunk.choices is not None: if len(chunk.choices) == 1: @@ -163,7 +168,7 @@ def __to_openai_messages(self, messages: list[Message]) -> list[dict]: "tool_call_id": action_result.action.tag, } for action_result in message.get_content_type(ActionResultMessageContent) - ] + ], ) else: # ToolAction calls are attached to the assistant message that originally generated them. @@ -186,12 +191,12 @@ def __to_openai_messages(self, messages: list[Message]) -> list[dict]: { "tool_calls": [ self.__to_openai_message_content(action_call) for action_call in action_call_content - ] + ], } if action_call_content else {} ), - } + }, ) return openai_messages @@ -257,11 +262,11 @@ def __to_prompt_stack_message_content(self, response: ChatCompletionMessage) -> name=ToolAction.from_native_tool_name(tool_call.function.name)[0], path=ToolAction.from_native_tool_name(tool_call.function.name)[1], input=json.loads(tool_call.function.arguments), - ) - ) + ), + ), ) for tool_call in response.tool_calls - ] + ], ) return content diff --git a/griptape/drivers/rerank/cohere_rerank_driver.py b/griptape/drivers/rerank/cohere_rerank_driver.py index 36956452c..12793846b 100644 --- a/griptape/drivers/rerank/cohere_rerank_driver.py +++ b/griptape/drivers/rerank/cohere_rerank_driver.py @@ -20,7 +20,7 @@ class CohereRerankDriver(BaseRerankDriver): api_key: str = field(metadata={"serializable": True}) client: Client = field( - default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True) + default=Factory(lambda self: import_optional_dependency("cohere").Client(self.api_key), takes_self=True), ) def run(self, query: str, artifacts: list[TextArtifact]) -> list[TextArtifact]: diff --git a/griptape/drivers/sql/amazon_redshift_sql_driver.py b/griptape/drivers/sql/amazon_redshift_sql_driver.py index 00391dc63..fc97d4e7e 100644 --- a/griptape/drivers/sql/amazon_redshift_sql_driver.py +++ b/griptape/drivers/sql/amazon_redshift_sql_driver.py @@ -21,7 +21,8 @@ class AmazonRedshiftSqlDriver(BaseSqlDriver): database_credentials_secret_arn: Optional[str] = field(default=None, kw_only=True) wait_for_query_completion_sec: float = field(default=0.3, kw_only=True) client: Any = field( - default=Factory(lambda self: self.session.client("redshift-data"), takes_self=True), kw_only=True + default=Factory(lambda self: self.session.client("redshift-data"), takes_self=True), + kw_only=True, ) @workgroup_name.validator # pyright: ignore[reportAttributeAccessIssue] @@ -82,7 +83,8 @@ def execute_query_raw(self, query: str) -> Optional[list[dict[str, Optional[Any] while "NextToken" in statement_result: statement_result = self.client.get_statement_result( - Id=response_id, NextToken=statement_result["NextToken"] + Id=response_id, + NextToken=statement_result["NextToken"], ) results = results + response.get("Records", []) diff --git a/griptape/drivers/sql/snowflake_sql_driver.py b/griptape/drivers/sql/snowflake_sql_driver.py index 7af4c78cc..a2d3eaead 100644 --- a/griptape/drivers/sql/snowflake_sql_driver.py +++ b/griptape/drivers/sql/snowflake_sql_driver.py @@ -20,7 +20,8 @@ class SnowflakeSqlDriver(BaseSqlDriver): # Creator bypasses the URL param # https://docs.sqlalchemy.org/en/14/core/engines.html#sqlalchemy.create_engine.params.creator lambda self: import_optional_dependency("sqlalchemy").create_engine( - "snowflake://not@used/db", creator=self.connection_func + "snowflake://not@used/db", + creator=self.connection_func, ), takes_self=True, ), diff --git a/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py b/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py index f2cda50be..00b90a819 100644 --- a/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py +++ b/griptape/drivers/structure_run/griptape_cloud_structure_run_driver.py @@ -15,7 +15,8 @@ class GriptapeCloudStructureRunDriver(BaseStructureRunDriver): base_url: str = field(default="https://cloud.griptape.ai", kw_only=True) api_key: str = field(kw_only=True) headers: dict = field( - default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True + default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), + kw_only=True, ) structure_id: str = field(kw_only=True) structure_run_wait_time_interval: int = field(default=2, kw_only=True) @@ -29,7 +30,9 @@ def try_run(self, *args: BaseArtifact) -> BaseArtifact: try: response: Response = post( - url, json={"args": [arg.value for arg in args], "env": self.env}, headers=self.headers + url, + json={"args": [arg.value for arg in args], "env": self.env}, + headers=self.headers, ) response.raise_for_status() response_json = response.json() @@ -57,7 +60,7 @@ def _get_structure_run_result(self, structure_run_id: str) -> InfoArtifact | Tex if wait_attempts >= self.structure_run_max_wait_time_attempts: return ErrorArtifact( - f"Failed to get Run result after {self.structure_run_max_wait_time_attempts} attempts." + f"Failed to get Run result after {self.structure_run_max_wait_time_attempts} attempts.", ) if status != "SUCCEEDED": diff --git a/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py b/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py index 96d0ded0c..f4be58162 100644 --- a/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/elevenlabs_text_to_speech_driver.py @@ -25,7 +25,10 @@ class ElevenLabsTextToSpeechDriver(BaseTextToSpeechDriver): def try_text_to_audio(self, prompts: list[str]) -> AudioArtifact: audio = self.client.generate( - text=". ".join(prompts), voice=self.voice, model=self.model, output_format=self.output_format + text=". ".join(prompts), + voice=self.voice, + model=self.model, + output_format=self.output_format, ) content = b"" diff --git a/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py b/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py index 8d8a81ad2..cb0c5340d 100644 --- a/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/openai_text_to_speech_driver.py @@ -13,7 +13,9 @@ class OpenAiTextToSpeechDriver(BaseTextToSpeechDriver): model: str = field(default="tts-1", kw_only=True, metadata={"serializable": True}) voice: Literal["alloy", "echo", "fable", "onyx", "nova", "shimmer"] = field( - default="alloy", kw_only=True, metadata={"serializable": True} + default="alloy", + kw_only=True, + metadata={"serializable": True}, ) format: Literal["mp3", "opus", "aac", "flac"] = field(default="mp3", kw_only=True, metadata={"serializable": True}) api_type: str = field(default=openai.api_type, kw_only=True) @@ -25,12 +27,15 @@ class OpenAiTextToSpeechDriver(BaseTextToSpeechDriver): default=Factory( lambda self: openai.OpenAI(api_key=self.api_key, base_url=self.base_url, organization=self.organization), takes_self=True, - ) + ), ) def try_text_to_audio(self, prompts: list[str]) -> AudioArtifact: response = self.client.audio.speech.create( - input=". ".join(prompts), voice=self.voice, model=self.model, response_format=self.format + input=". ".join(prompts), + voice=self.voice, + model=self.model, + response_format=self.format, ) return AudioArtifact(value=response.content, format=self.format) diff --git a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py index 140e429f1..14e3d81dc 100644 --- a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py @@ -28,10 +28,12 @@ class AmazonOpenSearchVectorStoreDriver(OpenSearchVectorStoreDriver): http_auth: str | tuple[str, str] = field( default=Factory( lambda self: import_optional_dependency("opensearchpy").AWSV4SignerAuth( - self.session.get_credentials(), self.session.region_name, self.service + self.session.get_credentials(), + self.session.region_name, + self.service, ), takes_self=True, - ) + ), ) client: OpenSearch = field( @@ -44,7 +46,7 @@ class AmazonOpenSearchVectorStoreDriver(OpenSearchVectorStoreDriver): connection_class=import_optional_dependency("opensearchpy").RequestsHttpConnection, ), takes_self=True, - ) + ), ) def upsert_vector( diff --git a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py index a1043040b..c4c7ef912 100644 --- a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py +++ b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py @@ -43,8 +43,8 @@ def query( "k": min(count * self.num_candidates_multiplier, self.MAX_NUM_CANDIDATES), }, "returnStoredSource": True, - } - } + }, + }, ) if namespace: diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 9f9a13ea2..78407b254 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -37,16 +37,20 @@ def to_artifact(self) -> BaseArtifact: embedding_driver: BaseEmbeddingDriver = field(kw_only=True, metadata={"serializable": True}) futures_executor_fn: Callable[[], futures.Executor] = field( - default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), + kw_only=True, ) def upsert_text_artifacts( - self, artifacts: list[TextArtifact] | dict[str, list[TextArtifact]], meta: Optional[dict] = None, **kwargs + self, + artifacts: list[TextArtifact] | dict[str, list[TextArtifact]], + meta: Optional[dict] = None, + **kwargs, ) -> None: with self.futures_executor_fn() as executor: if isinstance(artifacts, list): utils.execute_futures_list( - [executor.submit(self.upsert_text_artifact, a, None, meta, **kwargs) for a in artifacts] + [executor.submit(self.upsert_text_artifact, a, None, meta, **kwargs) for a in artifacts], ) else: utils.execute_futures_dict( @@ -54,7 +58,7 @@ def upsert_text_artifacts( namespace: executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) for namespace, artifact_list in artifacts.items() for a in artifact_list - } + }, ) def upsert_text_artifact( diff --git a/griptape/drivers/vector/dummy_vector_store_driver.py b/griptape/drivers/vector/dummy_vector_store_driver.py index 998b7a747..2b659ab62 100644 --- a/griptape/drivers/vector/dummy_vector_store_driver.py +++ b/griptape/drivers/vector/dummy_vector_store_driver.py @@ -11,7 +11,9 @@ @define() class DummyVectorStoreDriver(BaseVectorStoreDriver): embedding_driver: BaseEmbeddingDriver = field( - kw_only=True, default=Factory(lambda: DummyEmbeddingDriver()), metadata={"serializable": True} + kw_only=True, + default=Factory(lambda: DummyEmbeddingDriver()), + metadata={"serializable": True}, ) def delete_vector(self, vector_id: str) -> None: diff --git a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py index 2f3417f04..4929c58f2 100644 --- a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -27,10 +27,14 @@ class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): knowledge_base_id: str = field(kw_only=True, metadata={"serializable": True}) base_url: str = field(default="https://cloud.griptape.ai", kw_only=True) headers: dict = field( - default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True + default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), + kw_only=True, ) embedding_driver: BaseEmbeddingDriver = field( - default=Factory(lambda: DummyEmbeddingDriver()), metadata={"serializable": True}, kw_only=True, init=False + default=Factory(lambda: DummyEmbeddingDriver()), + metadata={"serializable": True}, + kw_only=True, + init=False, ) def upsert_vector( diff --git a/griptape/drivers/vector/local_vector_store_driver.py b/griptape/drivers/vector/local_vector_store_driver.py index f855f4228..f9520c0be 100644 --- a/griptape/drivers/vector/local_vector_store_driver.py +++ b/griptape/drivers/vector/local_vector_store_driver.py @@ -61,7 +61,10 @@ def upsert_vector( with self.thread_lock: self.entries[self._namespaced_vector_id(vector_id, namespace)] = self.Entry( - id=vector_id, vector=vector, meta=meta, namespace=namespace + id=vector_id, + vector=vector, + meta=meta, + namespace=namespace, ) if self.persist_file is not None: diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index 08c7b89bb..0c8940238 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -29,7 +29,8 @@ class MarqoVectorStoreDriver(BaseVectorStoreDriver): url: str = field(kw_only=True, metadata={"serializable": True}) mq: Optional[marqo.Client] = field( default=Factory( - lambda self: import_optional_dependency("marqo").Client(self.url, api_key=self.api_key), takes_self=True + lambda self: import_optional_dependency("marqo").Client(self.url, api_key=self.api_key), + takes_self=True, ), kw_only=True, ) @@ -158,7 +159,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD vector=doc["_tensor_facets"][0]["_embedding"], meta={k: v for k, v in doc.items() if k not in ["_id", "_tensor_facets", "_found"]}, namespace=doc.get("namespace"), - ) + ), ) return entries diff --git a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py index e27f48b79..3a96a9741 100644 --- a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py +++ b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py @@ -33,12 +33,15 @@ class MongoDbAtlasVectorStoreDriver(BaseVectorStoreDriver): index_name: str = field(kw_only=True, metadata={"serializable": True}) vector_path: str = field(kw_only=True, metadata={"serializable": True}) num_candidates_multiplier: int = field( - default=10, kw_only=True, metadata={"serializable": True} + default=10, + kw_only=True, + metadata={"serializable": True}, ) # https://www.mongodb.com/docs/atlas/atlas-vector-search/vector-search-stage/#fields client: MongoClient = field( default=Factory( - lambda self: import_optional_dependency("pymongo").MongoClient(self.connection_string), takes_self=True - ) + lambda self: import_optional_dependency("pymongo").MongoClient(self.connection_string), + takes_self=True, + ), ) def get_collection(self) -> Collection: @@ -64,7 +67,9 @@ def upsert_vector( vector_id = str(result.inserted_id) else: collection.replace_one( - {"_id": vector_id}, {self.vector_path: vector, "namespace": namespace, "meta": meta}, upsert=True + {"_id": vector_id}, + {self.vector_path: vector, "namespace": namespace, "meta": meta}, + upsert=True, ) return vector_id @@ -84,7 +89,10 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona return doc else: return BaseVectorStoreDriver.Entry( - id=str(doc["_id"]), vector=doc[self.vector_path], namespace=doc["namespace"], meta=doc["meta"] + id=str(doc["_id"]), + vector=doc[self.vector_path], + namespace=doc["namespace"], + meta=doc["meta"], ) def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: @@ -97,7 +105,10 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD return [ BaseVectorStoreDriver.Entry( - id=str(doc["_id"]), vector=doc[self.vector_path], namespace=doc["namespace"], meta=doc["meta"] + id=str(doc["_id"]), + vector=doc[self.vector_path], + namespace=doc["namespace"], + meta=doc["meta"], ) for doc in cursor ] @@ -131,7 +142,7 @@ def query( "queryVector": vector, "numCandidates": min(count * self.num_candidates_multiplier, self.MAX_NUM_CANDIDATES), "limit": count, - } + }, }, { "$project": { @@ -140,7 +151,7 @@ def query( "namespace": 1, "meta": 1, "score": {"$meta": "vectorSearchScore"}, - } + }, }, ] diff --git a/griptape/drivers/vector/opensearch_vector_store_driver.py b/griptape/drivers/vector/opensearch_vector_store_driver.py index 3819cf791..31921a0df 100644 --- a/griptape/drivers/vector/opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/opensearch_vector_store_driver.py @@ -43,7 +43,7 @@ class OpenSearchVectorStoreDriver(BaseVectorStoreDriver): connection_class=import_optional_dependency("opensearchpy").RequestsHttpConnection, ), takes_self=True, - ) + ), ) def upsert_vector( @@ -144,8 +144,11 @@ def query( if namespace: query_body["query"] = { "bool": { - "must": [{"match": {"namespace": namespace}}, {"knn": {field_name: {"vector": vector, "k": count}}}] - } + "must": [ + {"match": {"namespace": namespace}}, + {"knn": {field_name: {"vector": vector, "k": count}}}, + ], + }, } response = self.client.search(index=self.index_name, body=query_body) diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index 61c789243..ffc7a7516 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -61,7 +61,10 @@ def __attrs_post_init__(self) -> None: self.engine = cast(Engine, create_engine(self.connection_string, **self.create_engine_params)) def setup( - self, create_schema: bool = True, install_uuid_extension: bool = True, install_vector_extension: bool = True + self, + create_schema: bool = True, + install_uuid_extension: bool = True, + install_vector_extension: bool = True, ) -> None: """Provides a mechanism to initialize the database schema and extensions.""" if install_uuid_extension: @@ -113,7 +116,10 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD return [ BaseVectorStoreDriver.Entry( - id=str(result.id), vector=result.vector, namespace=result.namespace, meta=result.meta + id=str(result.id), + vector=result.vector, + namespace=result.namespace, + meta=result.meta, ) for result in results ] diff --git a/griptape/drivers/vector/pinecone_vector_store_driver.py b/griptape/drivers/vector/pinecone_vector_store_driver.py index 634a707e7..240829b7c 100644 --- a/griptape/drivers/vector/pinecone_vector_store_driver.py +++ b/griptape/drivers/vector/pinecone_vector_store_driver.py @@ -21,7 +21,9 @@ class PineconeVectorStoreDriver(BaseVectorStoreDriver): def __attrs_post_init__(self) -> None: pinecone = import_optional_dependency("pinecone").Pinecone( - api_key=self.api_key, environment=self.environment, project_name=self.project_name + api_key=self.api_key, + environment=self.environment, + project_name=self.project_name, ) self.index = pinecone.Index(self.index_name) @@ -50,7 +52,10 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona vector = vectors[0] return BaseVectorStoreDriver.Entry( - id=vector["id"], meta=vector["metadata"], vector=vector["values"], namespace=result["namespace"] + id=vector["id"], + meta=vector["metadata"], + vector=vector["values"], + namespace=result["namespace"], ) else: return None @@ -61,12 +66,18 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD # https://community.pinecone.io/t/is-there-a-way-to-query-all-the-vectors-and-or-metadata-from-a-namespace/797/5 results = self.index.query( - vector=self.embedding_driver.embed_string(""), top_k=10000, include_metadata=True, namespace=namespace + vector=self.embedding_driver.embed_string(""), + top_k=10000, + include_metadata=True, + namespace=namespace, ) return [ BaseVectorStoreDriver.Entry( - id=r["id"], vector=r["values"], meta=r["metadata"], namespace=results["namespace"] + id=r["id"], + vector=r["values"], + meta=r["metadata"], + namespace=results["namespace"], ) for r in results["matches"] ] @@ -94,7 +105,11 @@ def query( return [ BaseVectorStoreDriver.Entry( - id=r["id"], vector=r["values"], score=r["score"], meta=r["metadata"], namespace=results["namespace"] + id=r["id"], + vector=r["values"], + score=r["score"], + meta=r["metadata"], + namespace=results["namespace"], ) for r in results["matches"] ] diff --git a/griptape/drivers/vector/qdrant_vector_store_driver.py b/griptape/drivers/vector/qdrant_vector_store_driver.py index a5162f754..a92e9a060 100644 --- a/griptape/drivers/vector/qdrant_vector_store_driver.py +++ b/griptape/drivers/vector/qdrant_vector_store_driver.py @@ -47,7 +47,9 @@ class QdrantVectorStoreDriver(BaseVectorStoreDriver): https: bool = field(default=None, kw_only=True, metadata={"serializable": True}) prefix: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) force_disable_check_same_thread: Optional[bool] = field( - default=False, kw_only=True, metadata={"serializable": True} + default=False, + kw_only=True, + metadata={"serializable": True}, ) timeout: Optional[int] = field(default=5, kw_only=True, metadata={"serializable": True}) distance: str = field(default=DEFAULT_DISTANCE, kw_only=True, metadata={"serializable": True}) @@ -153,7 +155,9 @@ def upsert_vector( meta[self.content_payload_key] = content points = import_optional_dependency("qdrant_client.http.models").Batch( - ids=[vector_id], vectors=[vector], payloads=[meta] if meta else None + ids=[vector_id], + vectors=[vector], + payloads=[meta] if meta else None, ) self.client.upsert(collection_name=self.collection_name, points=points) diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index 3008760b2..aec02e59a 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -37,10 +37,14 @@ class RedisVectorStoreDriver(BaseVectorStoreDriver): client: Redis = field( default=Factory( lambda self: import_optional_dependency("redis").Redis( - host=self.host, port=self.port, db=self.db, password=self.password, decode_responses=False + host=self.host, + port=self.port, + db=self.db, + password=self.password, + decode_responses=False, ), takes_self=True, - ) + ), ) def upsert_vector( @@ -149,7 +153,7 @@ def query( score=float(document.score), meta=metadata, namespace=namespace, - ) + ), ) return query_results diff --git a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py index 92d2c6244..d285d773e 100644 --- a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py @@ -31,7 +31,8 @@ class MarkdownifyWebScraperDriver(BaseWebScraperDriver): include_links: bool = field(default=True, kw_only=True) exclude_tags: list[str] = field( - default=Factory(lambda self: self.DEFAULT_EXCLUDE_TAGS, takes_self=True), kw_only=True + default=Factory(lambda self: self.DEFAULT_EXCLUDE_TAGS, takes_self=True), + kw_only=True, ) exclude_classes: list[str] = field(default=Factory(list), kw_only=True) exclude_ids: list[str] = field(default=Factory(list), kw_only=True) @@ -78,7 +79,7 @@ def skip_loading_images(route): # Remove unwanted elements exclude_selector = ",".join( - self.exclude_tags + [f".{c}" for c in self.exclude_classes] + [f"#{i}" for i in self.exclude_ids] + self.exclude_tags + [f".{c}" for c in self.exclude_classes] + [f"#{i}" for i in self.exclude_ids], ) if exclude_selector: for s in soup.select(exclude_selector): diff --git a/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py b/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py index f0adfae22..0763155d5 100644 --- a/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/trafilatura_web_scraper_driver.py @@ -31,7 +31,10 @@ def scrape_url(self, url: str) -> TextArtifact: raise Exception("can't access URL") else: extracted_page = trafilatura.extract( - page, include_links=self.include_links, output_format="json", config=config + page, + include_links=self.include_links, + output_format="json", + config=config, ) if not extracted_page: diff --git a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py index 7e5c8b287..e701e8e0c 100644 --- a/griptape/drivers/web_search/duck_duck_go_web_search_driver.py +++ b/griptape/drivers/web_search/duck_duck_go_web_search_driver.py @@ -23,10 +23,10 @@ def search(self, query: str, **kwargs) -> ListArtifact: return ListArtifact( [ TextArtifact( - json.dumps({"title": result["title"], "url": result["href"], "description": result["body"]}) + json.dumps({"title": result["title"], "url": result["href"], "description": result["body"]}), ) for result in results - ] + ], ) except Exception as e: raise Exception(f"Error searching '{query}' with DuckDuckGo: {e}") from e diff --git a/griptape/drivers/web_search/google_web_search_driver.py b/griptape/drivers/web_search/google_web_search_driver.py index 6d08a9561..26ac57342 100644 --- a/griptape/drivers/web_search/google_web_search_driver.py +++ b/griptape/drivers/web_search/google_web_search_driver.py @@ -39,5 +39,5 @@ def _search_google(self, query: str, **kwargs) -> list[dict]: else: raise Exception( f"Google Search API returned an error with status code " - f"{response.status_code} and reason '{response.reason}'" + f"{response.status_code} and reason '{response.reason}'", ) diff --git a/griptape/engines/extraction/base_extraction_engine.py b/griptape/engines/extraction/base_extraction_engine.py index e1974ca9e..f0a658fe7 100644 --- a/griptape/engines/extraction/base_extraction_engine.py +++ b/griptape/engines/extraction/base_extraction_engine.py @@ -41,10 +41,14 @@ def max_chunker_tokens(self) -> int: def min_response_tokens(self) -> int: return round( self.prompt_driver.tokenizer.max_input_tokens - - self.prompt_driver.tokenizer.max_input_tokens * self.max_token_multiplier + - self.prompt_driver.tokenizer.max_input_tokens * self.max_token_multiplier, ) @abstractmethod def extract( - self, text: str | ListArtifact, *, rulesets: Optional[list[Ruleset]] = None, **kwargs + self, + text: str | ListArtifact, + *, + rulesets: Optional[list[Ruleset]] = None, + **kwargs, ) -> ListArtifact | ErrorArtifact: ... diff --git a/griptape/engines/extraction/csv_extraction_engine.py b/griptape/engines/extraction/csv_extraction_engine.py index b3a578064..3184654b1 100644 --- a/griptape/engines/extraction/csv_extraction_engine.py +++ b/griptape/engines/extraction/csv_extraction_engine.py @@ -71,7 +71,7 @@ def _extract_rec( self.text_to_csv_rows( self.prompt_driver.run(PromptStack(messages=[Message(full_text, role=Message.USER_ROLE)])).value, column_names, - ) + ), ) return rows @@ -87,7 +87,7 @@ def _extract_rec( self.text_to_csv_rows( self.prompt_driver.run(PromptStack(messages=[Message(partial_text, role=Message.USER_ROLE)])).value, column_names, - ) + ), ) return self._extract_rec(chunks[1:], column_names, rows, rulesets=rulesets) diff --git a/griptape/engines/extraction/json_extraction_engine.py b/griptape/engines/extraction/json_extraction_engine.py index 2662f28c3..436fc093f 100644 --- a/griptape/engines/extraction/json_extraction_engine.py +++ b/griptape/engines/extraction/json_extraction_engine.py @@ -64,8 +64,8 @@ def _extract_rec( if self.prompt_driver.tokenizer.count_input_tokens_left(full_text) >= self.min_response_tokens: extractions.extend( self.json_to_text_artifacts( - self.prompt_driver.run(PromptStack(messages=[Message(full_text, role=Message.USER_ROLE)])).value - ) + self.prompt_driver.run(PromptStack(messages=[Message(full_text, role=Message.USER_ROLE)])).value, + ), ) return extractions @@ -79,8 +79,8 @@ def _extract_rec( extractions.extend( self.json_to_text_artifacts( - self.prompt_driver.run(PromptStack(messages=[Message(partial_text, role=Message.USER_ROLE)])).value - ) + self.prompt_driver.run(PromptStack(messages=[Message(partial_text, role=Message.USER_ROLE)])).value, + ), ) return self._extract_rec(chunks[1:], json_template_schema, extractions, rulesets=rulesets) diff --git a/griptape/engines/image/inpainting_image_generation_engine.py b/griptape/engines/image/inpainting_image_generation_engine.py index 63f91af2e..a87f6622b 100644 --- a/griptape/engines/image/inpainting_image_generation_engine.py +++ b/griptape/engines/image/inpainting_image_generation_engine.py @@ -28,5 +28,8 @@ def run( negative_prompts = self._ruleset_to_prompts(negative_prompts, negative_rulesets) return self.image_generation_driver.run_image_inpainting( - prompts, image=image, mask=mask, negative_prompts=negative_prompts + prompts, + image=image, + mask=mask, + negative_prompts=negative_prompts, ) diff --git a/griptape/engines/image/outpainting_image_generation_engine.py b/griptape/engines/image/outpainting_image_generation_engine.py index 4ede5044a..267a13817 100644 --- a/griptape/engines/image/outpainting_image_generation_engine.py +++ b/griptape/engines/image/outpainting_image_generation_engine.py @@ -28,5 +28,8 @@ def run( negative_prompts = self._ruleset_to_prompts(negative_prompts, negative_rulesets) return self.image_generation_driver.run_image_outpainting( - prompts, image=image, mask=mask, negative_prompts=negative_prompts + prompts, + image=image, + mask=mask, + negative_prompts=negative_prompts, ) diff --git a/griptape/engines/image/variation_image_generation_engine.py b/griptape/engines/image/variation_image_generation_engine.py index fa182a40b..56d29c7e1 100644 --- a/griptape/engines/image/variation_image_generation_engine.py +++ b/griptape/engines/image/variation_image_generation_engine.py @@ -27,5 +27,7 @@ def run( negative_prompts = self._ruleset_to_prompts(negative_prompts, negative_rulesets) return self.image_generation_driver.run_image_variation( - prompts=prompts, image=image, negative_prompts=negative_prompts + prompts=prompts, + image=image, + negative_prompts=negative_prompts, ) diff --git a/griptape/engines/rag/modules/base_rag_module.py b/griptape/engines/rag/modules/base_rag_module.py index c90ed182c..f2c8316a8 100644 --- a/griptape/engines/rag/modules/base_rag_module.py +++ b/griptape/engines/rag/modules/base_rag_module.py @@ -16,12 +16,12 @@ class BaseRagModule(ABC): name: str = field(default=Factory(lambda self: self.__class__.__name__, takes_self=True), kw_only=True) futures_executor_fn: Callable[[], futures.Executor] = field( - default=Factory(lambda: lambda: futures.ThreadPoolExecutor()) + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), ) def generate_query_prompt_stack(self, system_prompt: str, query: str) -> PromptStack: return PromptStack( - messages=[Message(system_prompt, role=Message.SYSTEM_ROLE), Message(query, role=Message.USER_ROLE)] + messages=[Message(system_prompt, role=Message.SYSTEM_ROLE), Message(query, role=Message.USER_ROLE)], ) def get_context_param(self, context: RagContext, key: str) -> Optional[Any]: diff --git a/griptape/engines/rag/modules/response/prompt_response_rag_module.py b/griptape/engines/rag/modules/response/prompt_response_rag_module.py index 7f9b4daf8..0b7cbd953 100644 --- a/griptape/engines/rag/modules/response/prompt_response_rag_module.py +++ b/griptape/engines/rag/modules/response/prompt_response_rag_module.py @@ -18,7 +18,7 @@ class PromptResponseRagModule(BaseResponseRagModule): answer_token_offset: int = field(default=400) prompt_driver: BasePromptDriver = field() generate_system_template: Callable[[RagContext, list[TextArtifact]], str] = field( - default=Factory(lambda self: self.default_system_template_generator, takes_self=True) + default=Factory(lambda self: self.default_system_template_generator, takes_self=True), ) def run(self, context: RagContext) -> RagContext: @@ -32,7 +32,7 @@ def run(self, context: RagContext) -> RagContext: system_prompt = self.generate_system_template(context, included_chunks) message_token_count = self.prompt_driver.tokenizer.count_tokens( - self.prompt_driver.prompt_stack_to_string(self.generate_query_prompt_stack(system_prompt, query)) + self.prompt_driver.prompt_stack_to_string(self.generate_query_prompt_stack(system_prompt, query)), ) if message_token_count + self.answer_token_offset >= tokenizer.max_input_tokens: diff --git a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py index 7ae5df226..b79668583 100644 --- a/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/text_loader_retrieval_rag_module.py @@ -24,7 +24,7 @@ class TextLoaderRetrievalRagModule(BaseRetrievalRagModule): source: Any = field() query_params: dict[str, Any] = field(factory=dict) process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], Sequence[TextArtifact]] = field( - default=Factory(lambda: lambda es: [e.to_artifact() for e in es]) + default=Factory(lambda: lambda es: [e.to_artifact() for e in es]), ) def run(self, context: RagContext) -> Sequence[TextArtifact]: diff --git a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py index cbe5e6852..0a07b4c50 100644 --- a/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py +++ b/griptape/engines/rag/modules/retrieval/vector_store_retrieval_rag_module.py @@ -20,7 +20,7 @@ class VectorStoreRetrievalRagModule(BaseRetrievalRagModule): vector_store_driver: BaseVectorStoreDriver = field() query_params: dict[str, Any] = field(factory=dict) process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], Sequence[TextArtifact]] = field( - default=Factory(lambda: lambda es: [e.to_artifact() for e in es]) + default=Factory(lambda: lambda es: [e.to_artifact() for e in es]), ) def run(self, context: RagContext) -> Sequence[TextArtifact]: diff --git a/griptape/engines/rag/stages/base_rag_stage.py b/griptape/engines/rag/stages/base_rag_stage.py index 5484f6193..4f5a9bcd1 100644 --- a/griptape/engines/rag/stages/base_rag_stage.py +++ b/griptape/engines/rag/stages/base_rag_stage.py @@ -12,7 +12,7 @@ @define(kw_only=True) class BaseRagStage(ABC): futures_executor_fn: Callable[[], futures.Executor] = field( - default=Factory(lambda: lambda: futures.ThreadPoolExecutor()) + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), ) @abstractmethod diff --git a/griptape/engines/rag/stages/retrieval_rag_stage.py b/griptape/engines/rag/stages/retrieval_rag_stage.py index 8f552af3a..d0a92031e 100644 --- a/griptape/engines/rag/stages/retrieval_rag_stage.py +++ b/griptape/engines/rag/stages/retrieval_rag_stage.py @@ -48,7 +48,7 @@ def run(self, context: RagContext) -> RagContext: logging.info( f"RetrievalStage: deduplicated {chunks_before_dedup - chunks_after_dedup} " - f"chunks ({chunks_before_dedup} - {chunks_after_dedup})" + f"chunks ({chunks_before_dedup} - {chunks_after_dedup})", ) context.text_chunks = [a for a in results if isinstance(a, TextArtifact)] diff --git a/griptape/engines/summary/base_summary_engine.py b/griptape/engines/summary/base_summary_engine.py index e5ce6ee1e..a39d4d267 100644 --- a/griptape/engines/summary/base_summary_engine.py +++ b/griptape/engines/summary/base_summary_engine.py @@ -18,5 +18,8 @@ def summarize_text(self, text: str, *, rulesets: Optional[list[Ruleset]] = None) @abstractmethod def summarize_artifacts( - self, artifacts: ListArtifact, *, rulesets: Optional[list[Ruleset]] = None + self, + artifacts: ListArtifact, + *, + rulesets: Optional[list[Ruleset]] = None, ) -> TextArtifact: ... diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 61fe2c2ea..3cf0d6f3e 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -46,19 +46,23 @@ def max_chunker_tokens(self) -> int: def min_response_tokens(self) -> int: return round( self.prompt_driver.tokenizer.max_input_tokens - - self.prompt_driver.tokenizer.max_input_tokens * self.max_token_multiplier + - self.prompt_driver.tokenizer.max_input_tokens * self.max_token_multiplier, ) def summarize_artifacts(self, artifacts: ListArtifact, *, rulesets: Optional[list[Ruleset]] = None) -> TextArtifact: return self.summarize_artifacts_rec(cast(list[TextArtifact], artifacts.value), None, rulesets=rulesets) def summarize_artifacts_rec( - self, artifacts: list[TextArtifact], summary: Optional[str] = None, rulesets: Optional[list[Ruleset]] = None + self, + artifacts: list[TextArtifact], + summary: Optional[str] = None, + rulesets: Optional[list[Ruleset]] = None, ) -> TextArtifact: artifacts_text = self.chunk_joiner.join([a.to_text() for a in artifacts]) system_prompt = self.system_template_generator.render( - summary=summary, rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets) + summary=summary, + rulesets=J2("rulesets/rulesets.j2").render(rulesets=rulesets), ) user_prompt = self.user_template_generator.render(text=artifacts_text) @@ -72,8 +76,8 @@ def summarize_artifacts_rec( messages=[ Message(system_prompt, role=Message.SYSTEM_ROLE), Message(user_prompt, role=Message.USER_ROLE), - ] - ) + ], + ), ).to_artifact() if isinstance(result, TextArtifact): @@ -92,8 +96,8 @@ def summarize_artifacts_rec( messages=[ Message(system_prompt, role=Message.SYSTEM_ROLE), Message(partial_text, role=Message.USER_ROLE), - ] - ) + ], + ), ).value, rulesets=rulesets, ) diff --git a/griptape/loaders/base_loader.py b/griptape/loaders/base_loader.py index f9fa5d4bc..09551d9ab 100644 --- a/griptape/loaders/base_loader.py +++ b/griptape/loaders/base_loader.py @@ -18,7 +18,8 @@ @define class BaseLoader(ABC): futures_executor_fn: Callable[[], futures.Executor] = field( - default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), + kw_only=True, ) encoding: Optional[str] = field(default=None, kw_only=True) @@ -26,7 +27,10 @@ class BaseLoader(ABC): def load(self, source: Any, *args, **kwargs) -> BaseArtifact | Sequence[BaseArtifact]: ... def load_collection( - self, sources: list[Any], *args, **kwargs + self, + sources: list[Any], + *args, + **kwargs, ) -> Mapping[str, BaseArtifact | Sequence[BaseArtifact | Sequence[BaseArtifact]]]: # Create a dictionary before actually submitting the jobs to the executor # to avoid duplicate work. @@ -34,7 +38,7 @@ def load_collection( with self.futures_executor_fn() as executor: return execute_futures_dict( - {key: executor.submit(self.load, source, *args, **kwargs) for key, source in sources_by_key.items()} + {key: executor.submit(self.load, source, *args, **kwargs) for key, source in sources_by_key.items()}, ) def to_key(self, source: Any, *args, **kwargs) -> str: diff --git a/griptape/loaders/base_text_loader.py b/griptape/loaders/base_text_loader.py index eac16ab91..369f3f1fc 100644 --- a/griptape/loaders/base_text_loader.py +++ b/griptape/loaders/base_text_loader.py @@ -21,7 +21,8 @@ class BaseTextLoader(BaseLoader, ABC): MAX_TOKEN_RATIO = 0.5 tokenizer: OpenAiTokenizer = field( - default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)), kw_only=True + default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)), + kw_only=True, ) max_tokens: int = field( default=Factory(lambda self: round(self.tokenizer.max_input_tokens * self.MAX_TOKEN_RATIO), takes_self=True), @@ -29,7 +30,8 @@ class BaseTextLoader(BaseLoader, ABC): ) chunker: BaseChunker = field( default=Factory( - lambda self: TextChunker(tokenizer=self.tokenizer, max_tokens=self.max_tokens), takes_self=True + lambda self: TextChunker(tokenizer=self.tokenizer, max_tokens=self.max_tokens), + takes_self=True, ), kw_only=True, ) @@ -42,7 +44,8 @@ def load(self, source: Any, *args, **kwargs) -> ErrorArtifact | list[TextArtifac def load_collection(self, sources: list[Any], *args, **kwargs) -> dict[str, ErrorArtifact | list[TextArtifact]]: return cast( - dict[str, Union[ErrorArtifact, list[TextArtifact]]], super().load_collection(sources, *args, **kwargs) + dict[str, Union[ErrorArtifact, list[TextArtifact]]], + super().load_collection(sources, *args, **kwargs), ) def _text_to_artifacts(self, text: str) -> list[TextArtifact]: diff --git a/griptape/loaders/csv_loader.py b/griptape/loaders/csv_loader.py index 435ecb873..dc73ca52c 100644 --- a/griptape/loaders/csv_loader.py +++ b/griptape/loaders/csv_loader.py @@ -43,8 +43,12 @@ def load(self, source: bytes | str, *args, **kwargs) -> ErrorArtifact | list[Csv return artifacts def load_collection( - self, sources: list[bytes | str], *args, **kwargs + self, + sources: list[bytes | str], + *args, + **kwargs, ) -> dict[str, ErrorArtifact | list[CsvRowArtifact]]: return cast( - dict[str, Union[ErrorArtifact, list[CsvRowArtifact]]], super().load_collection(sources, *args, **kwargs) + dict[str, Union[ErrorArtifact, list[CsvRowArtifact]]], + super().load_collection(sources, *args, **kwargs), ) diff --git a/griptape/loaders/pdf_loader.py b/griptape/loaders/pdf_loader.py index d0622a9b4..0dfb959cf 100644 --- a/griptape/loaders/pdf_loader.py +++ b/griptape/loaders/pdf_loader.py @@ -21,7 +21,11 @@ class PdfLoader(BaseTextLoader): encoding: None = field(default=None, kw_only=True) def load( - self, source: bytes, password: Optional[str] = None, *args, **kwargs + self, + source: bytes, + password: Optional[str] = None, + *args, + **kwargs, ) -> ErrorArtifact | list[TextArtifact]: PdfReader = import_optional_dependency("pypdf").PdfReader reader = PdfReader(BytesIO(source), strict=True, password=password) @@ -29,5 +33,6 @@ def load( def load_collection(self, sources: list[bytes], *args, **kwargs) -> dict[str, ErrorArtifact | list[TextArtifact]]: return cast( - dict[str, Union[ErrorArtifact, list[TextArtifact]]], super().load_collection(sources, *args, **kwargs) + dict[str, Union[ErrorArtifact, list[TextArtifact]]], + super().load_collection(sources, *args, **kwargs), ) diff --git a/griptape/loaders/text_loader.py b/griptape/loaders/text_loader.py index 8eaa0b110..e356a2cdb 100644 --- a/griptape/loaders/text_loader.py +++ b/griptape/loaders/text_loader.py @@ -19,7 +19,8 @@ class TextLoader(BaseTextLoader): MAX_TOKEN_RATIO = 0.5 tokenizer: OpenAiTokenizer = field( - default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)), kw_only=True + default=Factory(lambda: OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL)), + kw_only=True, ) max_tokens: int = field( default=Factory(lambda self: round(self.tokenizer.max_input_tokens * self.MAX_TOKEN_RATIO), takes_self=True), @@ -27,7 +28,8 @@ class TextLoader(BaseTextLoader): ) chunker: TextChunker = field( default=Factory( - lambda self: TextChunker(tokenizer=self.tokenizer, max_tokens=self.max_tokens), takes_self=True + lambda self: TextChunker(tokenizer=self.tokenizer, max_tokens=self.max_tokens), + takes_self=True, ), kw_only=True, ) @@ -46,8 +48,12 @@ def load(self, source: bytes | str, *args, **kwargs) -> ErrorArtifact | list[Tex return self._text_to_artifacts(source) def load_collection( - self, sources: list[bytes | str], *args, **kwargs + self, + sources: list[bytes | str], + *args, + **kwargs, ) -> dict[str, ErrorArtifact | list[TextArtifact]]: return cast( - dict[str, Union[ErrorArtifact, list[TextArtifact]]], super().load_collection(sources, *args, **kwargs) + dict[str, Union[ErrorArtifact, list[TextArtifact]]], + super().load_collection(sources, *args, **kwargs), ) diff --git a/griptape/loaders/web_loader.py b/griptape/loaders/web_loader.py index e7265bba2..3798f9488 100644 --- a/griptape/loaders/web_loader.py +++ b/griptape/loaders/web_loader.py @@ -15,7 +15,8 @@ @define class WebLoader(BaseTextLoader): web_scraper_driver: BaseWebScraperDriver = field( - default=Factory(lambda: TrafilaturaWebScraperDriver()), kw_only=True + default=Factory(lambda: TrafilaturaWebScraperDriver()), + kw_only=True, ) def load(self, source: str, *args, **kwargs) -> ErrorArtifact | list[TextArtifact]: diff --git a/griptape/memory/structure/base_conversation_memory.py b/griptape/memory/structure/base_conversation_memory.py index 75450bcb9..c3d3c501e 100644 --- a/griptape/memory/structure/base_conversation_memory.py +++ b/griptape/memory/structure/base_conversation_memory.py @@ -80,7 +80,7 @@ def add_to_prompt_stack(self, prompt_stack: PromptStack, index: Optional[int] = # Convert the Prompt Stack into tokens left. tokens_left = prompt_driver.tokenizer.count_input_tokens_left( - prompt_driver.prompt_stack_to_string(temp_stack) + prompt_driver.prompt_stack_to_string(temp_stack), ) if tokens_left > 0: # There are still tokens left, no need to prune. diff --git a/griptape/memory/structure/summary_conversation_memory.py b/griptape/memory/structure/summary_conversation_memory.py index 5854aa058..17c3601c5 100644 --- a/griptape/memory/structure/summary_conversation_memory.py +++ b/griptape/memory/structure/summary_conversation_memory.py @@ -23,7 +23,8 @@ class SummaryConversationMemory(ConversationMemory): summary_index: int = field(default=0, kw_only=True, metadata={"serializable": True}) summary_template_generator: J2 = field(default=Factory(lambda: J2("memory/conversation/summary.j2")), kw_only=True) summarize_conversation_template_generator: J2 = field( - default=Factory(lambda: J2("memory/conversation/summarize_conversation.j2")), kw_only=True + default=Factory(lambda: J2("memory/conversation/summarize_conversation.j2")), + kw_only=True, ) @property @@ -78,7 +79,7 @@ def summarize_runs(self, previous_summary: str | None, runs: list[Run]) -> str | if len(runs) > 0: summary = self.summarize_conversation_template_generator.render(summary=previous_summary, runs=runs) return self.prompt_driver.run( - prompt_stack=PromptStack(messages=[Message(summary, role=Message.USER_ROLE)]) + prompt_stack=PromptStack(messages=[Message(summary, role=Message.USER_ROLE)]), ).to_text() else: return previous_summary diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 9bbf83433..d68d03209 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -60,10 +60,10 @@ def query(self, namespace: str, query: str, metadata: Any = None) -> BaseArtifac "query_params": { "namespace": namespace, "metadata": None if metadata is None else str(metadata), - } - } + }, + }, }, - ) + ), ).output if result is None: diff --git a/griptape/memory/task/task_memory.py b/griptape/memory/task/task_memory.py index 2e0639adc..79c375cdb 100644 --- a/griptape/memory/task/task_memory.py +++ b/griptape/memory/task/task_memory.py @@ -43,7 +43,10 @@ def find_storage(a): return find_storage(artifact) def process_output( - self, tool_activity: Callable, subtask: ActionsSubtask, output_artifact: BaseArtifact + self, + tool_activity: Callable, + subtask: ActionsSubtask, + output_artifact: BaseArtifact, ) -> BaseArtifact: from griptape.utils import J2 @@ -69,8 +72,10 @@ def process_output( if subtask.structure and subtask.structure.meta_memory: subtask.structure.meta_memory.add_entry( ActionSubtaskMetaEntry( - thought=subtask.thought, actions=subtask.actions_to_json(), answer=output - ) + thought=subtask.thought, + actions=subtask.actions_to_json(), + answer=output, + ), ) return InfoArtifact(output, name=namespace) diff --git a/griptape/mixins/activity_mixin.py b/griptape/mixins/activity_mixin.py index a00a70001..0178e342f 100644 --- a/griptape/mixins/activity_mixin.py +++ b/griptape/mixins/activity_mixin.py @@ -82,7 +82,7 @@ def activity_schema(self, activity: Callable) -> Optional[Schema]: raise Exception("This method is not an activity.") elif getattr(activity, "config")["schema"]: full_schema = { - "values": getattr(activity, "config")["schema"].schema if getattr(activity, "config")["schema"] else {} + "values": getattr(activity, "config")["schema"].schema if getattr(activity, "config")["schema"] else {}, } return Schema(full_schema) diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 1392bfb27..4aedd98ad 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -18,7 +18,7 @@ @define class Agent(Structure): input: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact] = field( - default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value="") + default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value=""), ) tools: list[BaseTool] = field(factory=list, kw_only=True) max_meta_memory_entries: Optional[int] = field(default=20, kw_only=True) diff --git a/griptape/structures/pipeline.py b/griptape/structures/pipeline.py index 81e9d31fd..b768cf6c6 100644 --- a/griptape/structures/pipeline.py +++ b/griptape/structures/pipeline.py @@ -63,7 +63,7 @@ def context(self, task: BaseTask) -> dict[str, Any]: "parent_output": task.parents[0].output.to_text() if task.parents and task.parents[0].output else None, "parent": task.parents[0] if task.parents else None, "child": task.children[0] if task.children else None, - } + }, ) return context diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 144394732..5e2615c9d 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -46,7 +46,8 @@ class Structure(ABC): prompt_driver: Optional[BasePromptDriver] = field(default=None) embedding_driver: Optional[BaseEmbeddingDriver] = field(default=None, kw_only=True) config: BaseStructureConfig = field( - default=Factory(lambda self: self.default_config, takes_self=True), kw_only=True + default=Factory(lambda self: self.default_config, takes_self=True), + kw_only=True, ) rulesets: list[Ruleset] = field(factory=list, kw_only=True) rules: list[Rule] = field(factory=list, kw_only=True) @@ -56,13 +57,15 @@ class Structure(ABC): event_listeners: list[EventListener] = field(factory=list, kw_only=True) conversation_memory: Optional[BaseConversationMemory] = field( default=Factory( - lambda self: ConversationMemory(driver=self.config.conversation_memory_driver), takes_self=True + lambda self: ConversationMemory(driver=self.config.conversation_memory_driver), + takes_self=True, ), kw_only=True, ) rag_engine: RagEngine = field(default=Factory(lambda self: self.default_rag_engine, takes_self=True), kw_only=True) task_memory: TaskMemory = field( - default=Factory(lambda self: self.default_task_memory, takes_self=True), kw_only=True + default=Factory(lambda self: self.default_task_memory, takes_self=True), + kw_only=True, ) meta_memory: MetaMemory = field(default=Factory(lambda: MetaMemory()), kw_only=True) fail_fast: bool = field(default=True, kw_only=True) @@ -171,7 +174,7 @@ def default_config(self) -> BaseStructureConfig: def default_rag_engine(self) -> RagEngine: return RagEngine( retrieval_stage=RetrievalRagStage( - retrieval_modules=[VectorStoreRetrievalRagModule(vector_store_driver=self.config.vector_store_driver)] + retrieval_modules=[VectorStoreRetrievalRagModule(vector_store_driver=self.config.vector_store_driver)], ), response_stage=ResponseRagStage( before_response_modules=[ @@ -195,7 +198,7 @@ def default_task_memory(self) -> TaskMemory: json_extraction_engine=JsonExtractionEngine(prompt_driver=self.config.prompt_driver), ), BlobArtifact: BlobArtifactStorage(), - } + }, ) def is_finished(self) -> bool: @@ -259,8 +262,10 @@ def before_run(self, args: Any) -> None: self.publish_event( StartStructureRunEvent( - structure_id=self.id, input_task_input=self.input_task.input, input_task_output=self.input_task.output - ) + structure_id=self.id, + input_task_input=self.input_task.input, + input_task_output=self.input_task.output, + ), ) self.resolve_relationships() diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index d83dee756..55dc63033 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -17,7 +17,8 @@ @define class Workflow(Structure): futures_executor_fn: Callable[[], futures.Executor] = field( - default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), + kw_only=True, ) @property @@ -114,7 +115,7 @@ def context(self, task: BaseTask) -> dict[str, Any]: "parents_output_text": task.parents_output_text, "parents": {parent.id: parent for parent in task.parents}, "children": {child.id: child for child in task.children}, - } + }, ) return context @@ -143,7 +144,9 @@ def __link_task_to_children(self, task: BaseTask, child_tasks: list[BaseTask]) - child_task.parent_ids.append(task.id) def __remove_old_parent_child_relationships( - self, parent_tasks: list[BaseTask], child_tasks: list[BaseTask] + self, + parent_tasks: list[BaseTask], + child_tasks: list[BaseTask], ) -> None: for parent_task in parent_tasks: for child_task in child_tasks: diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index d384acde9..3a44dc3e6 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -89,7 +89,7 @@ def before_run(self) -> None: subtask_parent_task_id=self.parent_task_id, subtask_thought=self.thought, subtask_actions=self.actions_to_dicts(), - ) + ), ) parts = [ @@ -155,7 +155,7 @@ def after_run(self) -> None: subtask_parent_task_id=self.parent_task_id, subtask_thought=self.thought, subtask_actions=self.actions_to_dicts(), - ) + ), ) self.structure.logger.info(f"Subtask {self.id}\nResponse: {response}") @@ -185,7 +185,8 @@ def actions_to_json(self) -> str: return json.dumps(self.actions_to_dicts(), indent=2) def _process_task_input( - self, task_input: str | tuple | list | BaseArtifact | Callable[[BaseTask], BaseArtifact] + self, + task_input: str | tuple | list | BaseArtifact | Callable[[BaseTask], BaseArtifact], ) -> TextArtifact | ListArtifact: if isinstance(task_input, (TextArtifact, ListArtifact)): return task_input diff --git a/griptape/tasks/audio_transcription_task.py b/griptape/tasks/audio_transcription_task.py index cc36f4eae..3a4b17b9e 100644 --- a/griptape/tasks/audio_transcription_task.py +++ b/griptape/tasks/audio_transcription_task.py @@ -14,7 +14,9 @@ @define class AudioTranscriptionTask(BaseAudioInputTask): _audio_transcription_engine: AudioTranscriptionEngine = field( - default=None, kw_only=True, alias="audio_transcription_engine" + default=None, + kw_only=True, + alias="audio_transcription_engine", ) @property @@ -22,7 +24,7 @@ def audio_transcription_engine(self) -> AudioTranscriptionEngine: if self._audio_transcription_engine is None: if self.structure is not None: self._audio_transcription_engine = AudioTranscriptionEngine( - audio_transcription_driver=self.structure.config.audio_transcription_driver + audio_transcription_driver=self.structure.config.audio_transcription_driver, ) else: raise ValueError("Audio Generation Engine is not set.") diff --git a/griptape/tasks/base_multi_text_input_task.py b/griptape/tasks/base_multi_text_input_task.py index 3804a749f..2891e52d7 100644 --- a/griptape/tasks/base_multi_text_input_task.py +++ b/griptape/tasks/base_multi_text_input_task.py @@ -16,7 +16,8 @@ class BaseMultiTextInputTask(RuleMixin, BaseTask, ABC): DEFAULT_INPUT_TEMPLATE = "{{ args[0] }}" _input: tuple[str, ...] | tuple[TextArtifact, ...] | tuple[Callable[[BaseTask], TextArtifact], ...] = field( - default=Factory(lambda self: (self.DEFAULT_INPUT_TEMPLATE,), takes_self=True), alias="input" + default=Factory(lambda self: (self.DEFAULT_INPUT_TEMPLATE,), takes_self=True), + alias="input", ) @property @@ -31,12 +32,13 @@ def input(self) -> ListArtifact: TextArtifact(J2().render_from_string(input_template, **self.full_context)) for input_template in self._input if isinstance(input_template, str) - ] + ], ) @input.setter def input( - self, value: tuple[str, ...] | tuple[TextArtifact, ...] | tuple[Callable[[BaseTask], TextArtifact], ...] + self, + value: tuple[str, ...] | tuple[TextArtifact, ...] | tuple[Callable[[BaseTask], TextArtifact], ...], ) -> None: self._input = value diff --git a/griptape/tasks/base_task.py b/griptape/tasks/base_task.py index bf985a313..9efe37002 100644 --- a/griptape/tasks/base_task.py +++ b/griptape/tasks/base_task.py @@ -34,7 +34,8 @@ class State(Enum): structure: Optional[Structure] = field(default=None, init=False) context: dict[str, Any] = field(factory=dict, kw_only=True) futures_executor_fn: Callable[[], futures.Executor] = field( - default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), kw_only=True + default=Factory(lambda: lambda: futures.ThreadPoolExecutor()), + kw_only=True, ) @property @@ -113,7 +114,7 @@ def before_run(self) -> None: task_child_ids=self.child_ids, task_input=self.input, task_output=self.output, - ) + ), ) def after_run(self) -> None: @@ -125,7 +126,7 @@ def after_run(self) -> None: task_child_ids=self.child_ids, task_input=self.input, task_output=self.output, - ) + ), ) def execute(self) -> Optional[BaseArtifact]: diff --git a/griptape/tasks/base_text_input_task.py b/griptape/tasks/base_text_input_task.py index c5641bb14..d94cdf734 100644 --- a/griptape/tasks/base_text_input_task.py +++ b/griptape/tasks/base_text_input_task.py @@ -16,7 +16,8 @@ class BaseTextInputTask(RuleMixin, BaseTask, ABC): DEFAULT_INPUT_TEMPLATE = "{{ args[0] }}" _input: str | TextArtifact | Callable[[BaseTask], TextArtifact] = field( - default=DEFAULT_INPUT_TEMPLATE, alias="input" + default=DEFAULT_INPUT_TEMPLATE, + alias="input", ) @property diff --git a/griptape/tasks/image_query_task.py b/griptape/tasks/image_query_task.py index aac3c655b..527729b94 100644 --- a/griptape/tasks/image_query_task.py +++ b/griptape/tasks/image_query_task.py @@ -48,7 +48,7 @@ def input(self) -> ListArtifact: else: raise ValueError( "Input must be a tuple of a TextArtifact and a list of ImageArtifacts or a callable that " - "returns a tuple of a TextArtifact and a list of ImageArtifacts." + "returns a tuple of a TextArtifact and a list of ImageArtifacts.", ) @input.setter diff --git a/griptape/tasks/inpainting_image_generation_task.py b/griptape/tasks/inpainting_image_generation_task.py index 5c508b534..2096c60e4 100644 --- a/griptape/tasks/inpainting_image_generation_task.py +++ b/griptape/tasks/inpainting_image_generation_task.py @@ -29,7 +29,9 @@ class InpaintingImageGenerationTask(BaseImageGenerationTask): """ _image_generation_engine: InpaintingImageGenerationEngine = field( - default=None, kw_only=True, alias="image_generation_engine" + default=None, + kw_only=True, + alias="image_generation_engine", ) _input: ( tuple[str | TextArtifact, ImageArtifact, ImageArtifact] | Callable[[BaseTask], ListArtifact] | ListArtifact @@ -53,7 +55,8 @@ def input(self) -> ListArtifact: @input.setter def input( - self, value: tuple[str | TextArtifact, ImageArtifact, ImageArtifact] | Callable[[BaseTask], ListArtifact] + self, + value: tuple[str | TextArtifact, ImageArtifact, ImageArtifact] | Callable[[BaseTask], ListArtifact], ) -> None: self._input = value @@ -62,7 +65,7 @@ def image_generation_engine(self) -> InpaintingImageGenerationEngine: if self._image_generation_engine is None: if self.structure is not None: self._image_generation_engine = InpaintingImageGenerationEngine( - image_generation_driver=self.structure.config.image_generation_driver + image_generation_driver=self.structure.config.image_generation_driver, ) else: raise ValueError("Image Generation Engine is not set.") diff --git a/griptape/tasks/outpainting_image_generation_task.py b/griptape/tasks/outpainting_image_generation_task.py index 8e7b210a2..a23fafd0f 100644 --- a/griptape/tasks/outpainting_image_generation_task.py +++ b/griptape/tasks/outpainting_image_generation_task.py @@ -29,7 +29,9 @@ class OutpaintingImageGenerationTask(BaseImageGenerationTask): """ _image_generation_engine: OutpaintingImageGenerationEngine = field( - default=None, kw_only=True, alias="image_generation_engine" + default=None, + kw_only=True, + alias="image_generation_engine", ) _input: ( tuple[str | TextArtifact, ImageArtifact, ImageArtifact] | Callable[[BaseTask], ListArtifact] | ListArtifact @@ -53,7 +55,8 @@ def input(self) -> ListArtifact: @input.setter def input( - self, value: tuple[str | TextArtifact, ImageArtifact, ImageArtifact] | Callable[[BaseTask], ListArtifact] + self, + value: tuple[str | TextArtifact, ImageArtifact, ImageArtifact] | Callable[[BaseTask], ListArtifact], ) -> None: self._input = value @@ -62,7 +65,7 @@ def image_generation_engine(self) -> OutpaintingImageGenerationEngine: if self._image_generation_engine is None: if self.structure is not None: self._image_generation_engine = OutpaintingImageGenerationEngine( - image_generation_driver=self.structure.config.image_generation_driver + image_generation_driver=self.structure.config.image_generation_driver, ) else: raise ValueError("Image Generation Engine is not set.") diff --git a/griptape/tasks/prompt_image_generation_task.py b/griptape/tasks/prompt_image_generation_task.py index 01bfd4b87..66cffab3e 100644 --- a/griptape/tasks/prompt_image_generation_task.py +++ b/griptape/tasks/prompt_image_generation_task.py @@ -31,7 +31,9 @@ class PromptImageGenerationTask(BaseImageGenerationTask): _input: str | TextArtifact | Callable[[BaseTask], TextArtifact] = field(default=DEFAULT_INPUT_TEMPLATE) _image_generation_engine: PromptImageGenerationEngine = field( - default=None, kw_only=True, alias="image_generation_engine" + default=None, + kw_only=True, + alias="image_generation_engine", ) @property @@ -52,7 +54,7 @@ def image_generation_engine(self) -> PromptImageGenerationEngine: if self._image_generation_engine is None: if self.structure is not None: self._image_generation_engine = PromptImageGenerationEngine( - image_generation_driver=self.structure.config.image_generation_driver + image_generation_driver=self.structure.config.image_generation_driver, ) else: raise ValueError("Image Generation Engine is not set.") @@ -64,7 +66,9 @@ def image_generation_engine(self, value: PromptImageGenerationEngine) -> None: def run(self) -> ImageArtifact: image_artifact = self.image_generation_engine.run( - prompts=[self.input.to_text()], rulesets=self.all_rulesets, negative_rulesets=self.negative_rulesets + prompts=[self.input.to_text()], + rulesets=self.all_rulesets, + negative_rulesets=self.negative_rulesets, ) if self.output_dir or self.output_file: diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index 8562b1e0c..45511875f 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -19,7 +19,8 @@ class PromptTask(RuleMixin, BaseTask): _prompt_driver: Optional[BasePromptDriver] = field(default=None, kw_only=True, alias="prompt_driver") generate_system_template: Callable[[PromptTask], str] = field( - default=Factory(lambda self: self.default_system_template_generator, takes_self=True), kw_only=True + default=Factory(lambda self: self.default_system_template_generator, takes_self=True), + kw_only=True, ) _input: str | list | tuple | BaseArtifact | Callable[[BaseTask], BaseArtifact] = field( default=lambda task: task.full_context["args"][0] if task.full_context["args"] else TextArtifact(value=""), @@ -74,7 +75,7 @@ def preprocess(self, structure: Structure) -> PromptTask: def default_system_template_generator(self, _: PromptTask) -> str: return J2("tasks/prompt_task/system.j2").render( - rulesets=J2("rulesets/rulesets.j2").render(rulesets=self.all_rulesets) + rulesets=J2("rulesets/rulesets.j2").render(rulesets=self.all_rulesets), ) def before_run(self) -> None: @@ -93,7 +94,8 @@ def run(self) -> BaseArtifact: return message.to_artifact() def _process_task_input( - self, task_input: str | tuple | list | BaseArtifact | Callable[[BaseTask], BaseArtifact] + self, + task_input: str | tuple | list | BaseArtifact | Callable[[BaseTask], BaseArtifact], ) -> BaseArtifact: if isinstance(task_input, TextArtifact): task_input.value = J2().render_from_string(task_input.value, **self.full_context) diff --git a/griptape/tasks/text_to_speech_task.py b/griptape/tasks/text_to_speech_task.py index ab01e298c..3ca503dfe 100644 --- a/griptape/tasks/text_to_speech_task.py +++ b/griptape/tasks/text_to_speech_task.py @@ -39,7 +39,7 @@ def text_to_speech_engine(self) -> TextToSpeechEngine: if self._text_to_speech_engine is None: if self.structure is not None: self._text_to_speech_engine = TextToSpeechEngine( - text_to_speech_driver=self.structure.config.text_to_speech_driver + text_to_speech_driver=self.structure.config.text_to_speech_driver, ) else: raise ValueError("Audio Generation Engine is not set.") diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index 9132f53f5..8f3519c32 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -32,10 +32,12 @@ class ToolkitTask(PromptTask, ActionsSubtaskOriginMixin): task_memory: Optional[TaskMemory] = field(default=None, kw_only=True) subtasks: list[ActionsSubtask] = field(factory=list) generate_assistant_subtask_template: Callable[[ActionsSubtask], str] = field( - default=Factory(lambda self: self.default_assistant_subtask_template_generator, takes_self=True), kw_only=True + default=Factory(lambda self: self.default_assistant_subtask_template_generator, takes_self=True), + kw_only=True, ) generate_user_subtask_template: Callable[[ActionsSubtask], str] = field( - default=Factory(lambda self: self.default_user_subtask_template_generator, takes_self=True), kw_only=True + default=Factory(lambda self: self.default_user_subtask_template_generator, takes_self=True), + kw_only=True, ) response_stop_sequence: str = field(default=RESPONSE_STOP_SEQUENCE, kw_only=True) @@ -90,16 +92,16 @@ def prompt_stack(self) -> PromptStack: [ *([TextArtifact(s.thought)] if s.thought else []), *[ActionArtifact(a) for a in action_calls], - ] - ) + ], + ), ) stack.add_user_message( ListArtifact( [ *[ActionArtifact(a) for a in action_results], *([] if s.output else [TextArtifact("Please keep going")]), - ] - ) + ], + ), ) else: stack.add_assistant_message(self.generate_assistant_subtask_template(s)) @@ -134,12 +136,14 @@ def default_system_template_generator(self, _: PromptTask) -> str: def default_assistant_subtask_template_generator(self, subtask: ActionsSubtask) -> str: return J2("tasks/toolkit_task/assistant_subtask.j2").render( - stop_sequence=self.response_stop_sequence, subtask=subtask + stop_sequence=self.response_stop_sequence, + subtask=subtask, ) def default_user_subtask_template_generator(self, subtask: ActionsSubtask) -> str: return J2("tasks/toolkit_task/user_subtask.j2").render( - stop_sequence=self.response_stop_sequence, subtask=subtask + stop_sequence=self.response_stop_sequence, + subtask=subtask, ) def actions_schema(self) -> Schema: diff --git a/griptape/tasks/variation_image_generation_task.py b/griptape/tasks/variation_image_generation_task.py index c3e71e0b5..df4579efa 100644 --- a/griptape/tasks/variation_image_generation_task.py +++ b/griptape/tasks/variation_image_generation_task.py @@ -29,10 +29,12 @@ class VariationImageGenerationTask(BaseImageGenerationTask): """ _image_generation_engine: VariationImageGenerationEngine = field( - default=None, kw_only=True, alias="image_generation_engine" + default=None, + kw_only=True, + alias="image_generation_engine", ) _input: tuple[str | TextArtifact, ImageArtifact] | Callable[[BaseTask], ListArtifact] | ListArtifact = field( - default=None + default=None, ) @property @@ -60,7 +62,7 @@ def image_generation_engine(self) -> VariationImageGenerationEngine: if self._image_generation_engine is None: if self.structure is not None: self._image_generation_engine = VariationImageGenerationEngine( - image_generation_driver=self.structure.config.image_generation_driver + image_generation_driver=self.structure.config.image_generation_driver, ) else: raise ValueError("Image Generation Engine is not set.") diff --git a/griptape/tokenizers/anthropic_tokenizer.py b/griptape/tokenizers/anthropic_tokenizer.py index 0955a506b..ffa492740 100644 --- a/griptape/tokenizers/anthropic_tokenizer.py +++ b/griptape/tokenizers/anthropic_tokenizer.py @@ -17,7 +17,8 @@ class AnthropicTokenizer(BaseTokenizer): MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS = {"claude": 4096} client: Anthropic = field( - default=Factory(lambda: import_optional_dependency("anthropic").Anthropic()), kw_only=True + default=Factory(lambda: import_optional_dependency("anthropic").Anthropic()), + kw_only=True, ) def count_tokens(self, text: str) -> int: diff --git a/griptape/tokenizers/base_tokenizer.py b/griptape/tokenizers/base_tokenizer.py index 5b334f096..7bdfe523a 100644 --- a/griptape/tokenizers/base_tokenizer.py +++ b/griptape/tokenizers/base_tokenizer.py @@ -50,7 +50,7 @@ def _default_max_input_tokens(self) -> int: if tokens is None: logging.warning( - f"Model {self.model} not found in MODEL_PREFIXES_TO_MAX_INPUT_TOKENS, using default value of {self.DEFAULT_MAX_INPUT_TOKENS}." + f"Model {self.model} not found in MODEL_PREFIXES_TO_MAX_INPUT_TOKENS, using default value of {self.DEFAULT_MAX_INPUT_TOKENS}.", ) return self.DEFAULT_MAX_INPUT_TOKENS else: @@ -58,12 +58,13 @@ def _default_max_input_tokens(self) -> int: def _default_max_output_tokens(self) -> int: tokens = next( - (v for k, v in self.MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS.items() if self.model.startswith(k)), None + (v for k, v in self.MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS.items() if self.model.startswith(k)), + None, ) if tokens is None: logging.warning( - f"Model {self.model} not found in MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS, using default value of {self.DEFAULT_MAX_OUTPUT_TOKENS}." + f"Model {self.model} not found in MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS, using default value of {self.DEFAULT_MAX_OUTPUT_TOKENS}.", ) return self.DEFAULT_MAX_OUTPUT_TOKENS else: diff --git a/griptape/tokenizers/google_tokenizer.py b/griptape/tokenizers/google_tokenizer.py index 45e927cc9..87020bd96 100644 --- a/griptape/tokenizers/google_tokenizer.py +++ b/griptape/tokenizers/google_tokenizer.py @@ -18,7 +18,8 @@ class GoogleTokenizer(BaseTokenizer): api_key: str = field(kw_only=True, metadata={"serializable": True}) model_client: GenerativeModel = field( - default=Factory(lambda self: self._default_model_client(), takes_self=True), kw_only=True + default=Factory(lambda self: self._default_model_client(), takes_self=True), + kw_only=True, ) def count_tokens(self, text: str) -> int: diff --git a/griptape/tokenizers/huggingface_tokenizer.py b/griptape/tokenizers/huggingface_tokenizer.py index 63ddf0ea7..381289d63 100644 --- a/griptape/tokenizers/huggingface_tokenizer.py +++ b/griptape/tokenizers/huggingface_tokenizer.py @@ -21,7 +21,8 @@ class HuggingFaceTokenizer(BaseTokenizer): kw_only=True, ) max_input_tokens: int = field( - default=Factory(lambda self: self.tokenizer.model_max_length, takes_self=True), kw_only=True + default=Factory(lambda self: self.tokenizer.model_max_length, takes_self=True), + kw_only=True, ) max_output_tokens: int = field(default=4096, kw_only=True) diff --git a/griptape/tokenizers/openai_tokenizer.py b/griptape/tokenizers/openai_tokenizer.py index 13449f007..9cbbd6a03 100644 --- a/griptape/tokenizers/openai_tokenizer.py +++ b/griptape/tokenizers/openai_tokenizer.py @@ -45,10 +45,12 @@ class OpenAiTokenizer(BaseTokenizer): ] max_input_tokens: int = field( - kw_only=True, default=Factory(lambda self: self._default_max_input_tokens(), takes_self=True) + kw_only=True, + default=Factory(lambda self: self._default_max_input_tokens(), takes_self=True), ) max_output_tokens: int = field( - kw_only=True, default=Factory(lambda self: self._default_max_output_tokens(), takes_self=True) + kw_only=True, + default=Factory(lambda self: self._default_max_output_tokens(), takes_self=True), ) @property @@ -66,7 +68,8 @@ def _default_max_input_tokens(self) -> int: def _default_max_output_tokens(self) -> int: tokens = next( - (v for k, v in self.MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS.items() if self.model.startswith(k)), None + (v for k, v in self.MODEL_PREFIXES_TO_MAX_OUTPUT_TOKENS.items() if self.model.startswith(k)), + None, ) if tokens is None: @@ -119,7 +122,7 @@ def count_tokens(self, text: str | list[dict], model: Optional[str] = None) -> i raise NotImplementedError( f"""token_count() is not implemented for model {model}. See https://github.com/openai/openai-python/blob/main/chatml.md for - information on how messages are converted to tokens.""" + information on how messages are converted to tokens.""", ) num_tokens = 0 diff --git a/griptape/tokenizers/voyageai_tokenizer.py b/griptape/tokenizers/voyageai_tokenizer.py index 649f6e0cc..d5007cf7d 100644 --- a/griptape/tokenizers/voyageai_tokenizer.py +++ b/griptape/tokenizers/voyageai_tokenizer.py @@ -24,7 +24,8 @@ class VoyageAiTokenizer(BaseTokenizer): api_key: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) client: Client = field( default=Factory( - lambda self: import_optional_dependency("voyageai").Client(api_key=self.api_key), takes_self=True + lambda self: import_optional_dependency("voyageai").Client(api_key=self.api_key), + takes_self=True, ), kw_only=True, ) diff --git a/griptape/tools/audio_transcription_client/tool.py b/griptape/tools/audio_transcription_client/tool.py index 786fb406b..bf2dfc67f 100644 --- a/griptape/tools/audio_transcription_client/tool.py +++ b/griptape/tools/audio_transcription_client/tool.py @@ -26,7 +26,7 @@ class AudioTranscriptionClient(BaseTool): config={ "description": "This tool can be used to generate transcriptions of audio files on disk.", "schema": Schema({Literal("path", description="The paths to an audio file on disk."): str}), - } + }, ) def transcribe_audio_from_disk(self, params: dict) -> TextArtifact | ErrorArtifact: audio_path = params["values"]["path"] @@ -40,7 +40,7 @@ def transcribe_audio_from_disk(self, params: dict) -> TextArtifact | ErrorArtifa config={ "description": "This tool can be used to generate the transcription of an audio artifact in memory.", "schema": Schema({"schema": Schema({"memory_name": str, "artifact_namespace": str, "artifact_name": str})}), - } + }, ) def transcribe_audio_from_memory(self, params: dict[str, Any]) -> TextArtifact | ErrorArtifact: memory = self.find_input_memory(params["values"]["memory_name"]) @@ -51,7 +51,8 @@ def transcribe_audio_from_memory(self, params: dict[str, Any]) -> TextArtifact | return ErrorArtifact("memory not found") audio_artifact = cast( - AudioArtifact, load_artifact_from_memory(memory, artifact_namespace, artifact_name, AudioArtifact) + AudioArtifact, + load_artifact_from_memory(memory, artifact_namespace, artifact_name, AudioArtifact), ) return self.engine.run(audio_artifact) diff --git a/griptape/tools/aws_iam_client/tool.py b/griptape/tools/aws_iam_client/tool.py index b9f149b23..1be0251f0 100644 --- a/griptape/tools/aws_iam_client/tool.py +++ b/griptape/tools/aws_iam_client/tool.py @@ -27,14 +27,15 @@ class AwsIamClient(BaseAwsClient): "policy_name", description="PolicyName of the AWS IAM Policy embedded in the specified IAM user.", ): str, - } + }, ), - } + }, ) def get_user_policy(self, params: dict) -> TextArtifact | ErrorArtifact: try: policy = self.iam_client.get_user_policy( - UserName=params["values"]["user_name"], PolicyName=params["values"]["policy_name"] + UserName=params["values"]["user_name"], + PolicyName=params["values"]["policy_name"], ) return TextArtifact(policy["PolicyDocument"]) except Exception as e: @@ -52,9 +53,9 @@ def list_mfa_devices(self, _: dict) -> ListArtifact | ErrorArtifact: config={ "description": "Can be used to list policies for a given IAM user.", "schema": Schema( - {Literal("user_name", description="Username of the AWS IAM user for which to list policies."): str} + {Literal("user_name", description="Username of the AWS IAM user for which to list policies."): str}, ), - } + }, ) def list_user_policies(self, params: dict) -> ListArtifact | ErrorArtifact: try: diff --git a/griptape/tools/aws_s3_client/tool.py b/griptape/tools/aws_s3_client/tool.py index e69db8390..8f67195a1 100644 --- a/griptape/tools/aws_s3_client/tool.py +++ b/griptape/tools/aws_s3_client/tool.py @@ -26,10 +26,10 @@ class AwsS3Client(BaseAwsClient): Literal( "bucket_name", description="The bucket name that contains the object for which to get the ACL information.", - ): str - } + ): str, + }, ), - } + }, ) def get_bucket_acl(self, params: dict) -> TextArtifact | ErrorArtifact: try: @@ -42,9 +42,9 @@ def get_bucket_acl(self, params: dict) -> TextArtifact | ErrorArtifact: config={ "description": "Can be used to get an AWS S3 bucket policy.", "schema": Schema( - {Literal("bucket_name", description="The bucket name for which to get the bucket policy."): str} + {Literal("bucket_name", description="The bucket name for which to get the bucket policy."): str}, ), - } + }, ) def get_bucket_policy(self, params: dict) -> TextArtifact | ErrorArtifact: try: @@ -60,14 +60,15 @@ def get_bucket_policy(self, params: dict) -> TextArtifact | ErrorArtifact: { Literal("bucket_name", description="Name of the AWS S3 bucket for which to get an ACL."): str, Literal("object_key", description="Key of the object for which to get the ACL information."): str, - } + }, ), - } + }, ) def get_object_acl(self, params: dict) -> TextArtifact | ErrorArtifact: try: acl = self.s3_client.get_object_acl( - Bucket=params["values"]["bucket_name"], Key=params["values"]["object_key"] + Bucket=params["values"]["bucket_name"], + Key=params["values"]["object_key"], ) return TextArtifact(acl) except Exception as e: @@ -86,7 +87,7 @@ def list_s3_buckets(self, _: dict) -> ListArtifact | ErrorArtifact: config={ "description": "Can be used to list all objects in an AWS S3 bucket.", "schema": Schema({Literal("bucket_name", description="The name of the S3 bucket to list."): str}), - } + }, ) def list_objects(self, params: dict) -> ListArtifact | ErrorArtifact: try: @@ -108,9 +109,9 @@ def list_objects(self, params: dict) -> ListArtifact | ErrorArtifact: "artifact_namespace": str, "bucket_name": str, Literal("object_key", description="Destination object key name. For example, 'baz.txt'"): str, - } + }, ), - } + }, ) def upload_memory_artifacts_to_s3(self, params: dict) -> InfoArtifact | ErrorArtifact: memory = self.find_input_memory(params["values"]["memory_name"]) @@ -149,9 +150,9 @@ def upload_memory_artifacts_to_s3(self, params: dict) -> InfoArtifact | ErrorArt "bucket_name": str, Literal("object_key", description="Destination object key name. For example, 'baz.txt'"): str, "content": str, - } + }, ), - } + }, ) def upload_content_to_s3(self, params: dict) -> ErrorArtifact | InfoArtifact: content = params["values"]["content"] @@ -173,16 +174,18 @@ def upload_content_to_s3(self, params: dict) -> ErrorArtifact | InfoArtifact: Literal("objects", description="A list of bucket name and object key pairs to download"): [ { Literal( - "bucket_name", description="The name of the bucket to download the object from" + "bucket_name", + description="The name of the bucket to download the object from", ): str, Literal( - "object_key", description="The name of the object key to download from the bucket" + "object_key", + description="The name of the object key to download from the bucket", ): str, - } - ] - } + }, + ], + }, ), - } + }, ) def download_objects(self, params: dict) -> ListArtifact | ErrorArtifact: objects = params["values"]["objects"] @@ -203,5 +206,7 @@ def _upload_object(self, bucket_name: str, object_name: str, value: Any) -> None self.s3_client.create_bucket(Bucket=bucket_name) self.s3_client.upload_fileobj( - Fileobj=io.BytesIO(value.encode() if isinstance(value, str) else value), Bucket=bucket_name, Key=object_name + Fileobj=io.BytesIO(value.encode() if isinstance(value, str) else value), + Bucket=bucket_name, + Key=object_name, ) diff --git a/griptape/tools/base_google_client.py b/griptape/tools/base_google_client.py index 1269548f3..2a38d8ffe 100644 --- a/griptape/tools/base_google_client.py +++ b/griptape/tools/base_google_client.py @@ -21,7 +21,8 @@ def _build_client(self, scopes: list[str], service_name: str, version: str, owne from googleapiclient.discovery import build credentials = service_account.Credentials.from_service_account_info( - self.service_account_credentials, scopes=scopes + self.service_account_credentials, + scopes=scopes, ) return build(serviceName=service_name, version=version, credentials=credentials.with_subject(owner_email)) diff --git a/griptape/tools/base_griptape_cloud_client.py b/griptape/tools/base_griptape_cloud_client.py index 908f59b52..4f5692957 100644 --- a/griptape/tools/base_griptape_cloud_client.py +++ b/griptape/tools/base_griptape_cloud_client.py @@ -20,5 +20,6 @@ class BaseGriptapeCloudClient(BaseTool, ABC): base_url: str = field(default="https://cloud.griptape.ai", kw_only=True) api_key: str = field(kw_only=True) headers: dict = field( - default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True + default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), + kw_only=True, ) diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index b9cc21cdf..eb1689c86 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -99,9 +99,9 @@ def activity_schemas(self) -> list[Schema]: Literal("name"): self.name, Literal("path", description=self.activity_description(activity)): self.activity_name(activity), **self.activity_to_input( - activity + activity, ), # Unpack the dictionary in order to only add the key-values if there are any - } + }, ) for activity in self.activities() ] @@ -122,7 +122,11 @@ def before_run(self, activity: Callable, subtask: ActionsSubtask, action: ToolAc return action.input def run( - self, activity: Callable, subtask: ActionsSubtask, action: ToolAction, value: Optional[dict] + self, + activity: Callable, + subtask: ActionsSubtask, + action: ToolAction, + value: Optional[dict], ) -> BaseArtifact: activity_result = activity(value) @@ -136,7 +140,11 @@ def run( return result def after_run( - self, activity: Callable, subtask: ActionsSubtask, action: ToolAction, value: BaseArtifact + self, + activity: Callable, + subtask: ActionsSubtask, + action: ToolAction, + value: BaseArtifact, ) -> BaseArtifact: if value: if self.output_memory: diff --git a/griptape/tools/calculator/tool.py b/griptape/tools/calculator/tool.py index 04d6868e3..141d1a333 100644 --- a/griptape/tools/calculator/tool.py +++ b/griptape/tools/calculator/tool.py @@ -15,10 +15,10 @@ class Calculator(BaseTool): "expression", description="Arithmetic expression parsable in pure Python. Single line only. " "Don't use variables. Don't use any imports or external libraries", - ): str - } + ): str, + }, ), - } + }, ) def calculate(self, params: dict) -> BaseArtifact: import numexpr diff --git a/griptape/tools/computer/tool.py b/griptape/tools/computer/tool.py index 06129bfd6..08a1f6976 100644 --- a/griptape/tools/computer/tool.py +++ b/griptape/tools/computer/tool.py @@ -36,7 +36,8 @@ class Computer(BaseTool): kw_only=True, ) docker_client: DockerClient = field( - default=Factory(lambda self: self.default_docker_client(), takes_self=True), kw_only=True + default=Factory(lambda self: self.default_docker_client(), takes_self=True), + kw_only=True, ) _tempdir: Optional[tempfile.TemporaryDirectory] = field(default=None, kw_only=True) @@ -71,11 +72,12 @@ def install_dependencies(self, env: Optional[dict[str, str]] = None) -> None: { Literal("code", description="Python code to execute"): str, Literal( - "filename", description="name of the file to put the Python code in before executing it" + "filename", + description="name of the file to put the Python code in before executing it", ): str, - } + }, ), - } + }, ) def execute_code(self, params: dict) -> BaseArtifact: code = params["values"]["code"] @@ -87,7 +89,7 @@ def execute_code(self, params: dict) -> BaseArtifact: config={ "description": "Can be used to execute shell commands in Linux", "schema": Schema({Literal("command", description="shell command to execute"): str}), - } + }, ) def execute_command(self, params: dict) -> BaseArtifact: command = params["values"]["command"] diff --git a/griptape/tools/date_time/tool.py b/griptape/tools/date_time/tool.py index 886969575..728a3449a 100644 --- a/griptape/tools/date_time/tool.py +++ b/griptape/tools/date_time/tool.py @@ -26,10 +26,10 @@ def get_current_datetime(self, _: dict) -> BaseArtifact: "relative_date_string", description='Relative date in English. For example, "now EST", "20 minutes ago", ' '"in 2 days", "3 months, 1 week and 1 day ago", or "yesterday at 2pm"', - ): str - } + ): str, + }, ), - } + }, ) def get_relative_datetime(self, params: dict) -> BaseArtifact: from dateparser import parse diff --git a/griptape/tools/email_client/tool.py b/griptape/tools/email_client/tool.py index 622c21fa3..26c13bb9f 100644 --- a/griptape/tools/email_client/tool.py +++ b/griptape/tools/email_client/tool.py @@ -66,15 +66,15 @@ class EmailClient(BaseTool): { Literal("label", description="Label to retrieve emails from such as 'INBOX' or 'SENT'"): str, schema.Optional( - Literal("key", description="Optional key for filtering such as 'FROM' or 'SUBJECT'") + Literal("key", description="Optional key for filtering such as 'FROM' or 'SUBJECT'"), ): str, schema.Optional( - Literal("search_criteria", description="Optional search criteria to filter emails by key") + Literal("search_criteria", description="Optional search criteria to filter emails by key"), ): str, schema.Optional(Literal("max_count", description="Optional max email count")): int, - } + }, ), - } + }, ) def retrieve(self, params: dict) -> ListArtifact | ErrorArtifact: if self.mailboxes is None: @@ -89,7 +89,7 @@ def retrieve(self, params: dict) -> ListArtifact | ErrorArtifact: key=values.get("key"), search_criteria=values.get("search_criteria"), max_count=max_count, - ) + ), ) @activity( @@ -100,9 +100,9 @@ def retrieve(self, params: dict) -> ListArtifact | ErrorArtifact: Literal("to", description="Recipient's email address"): str, Literal("subject", description="Email subject"): str, Literal("body", description="Email body"): str, - } + }, ), - } + }, ) def send(self, params: dict) -> InfoArtifact | ErrorArtifact: values = params["values"] diff --git a/griptape/tools/file_manager/tool.py b/griptape/tools/file_manager/tool.py index db6ef451a..c0cb691ea 100644 --- a/griptape/tools/file_manager/tool.py +++ b/griptape/tools/file_manager/tool.py @@ -25,9 +25,9 @@ class FileManager(BaseTool): config={ "description": "Can be used to list files on disk", "schema": Schema( - {Literal("path", description="Relative path in the POSIX format. For example, 'foo/bar'"): str} + {Literal("path", description="Relative path in the POSIX format. For example, 'foo/bar'"): str}, ), - } + }, ) def list_files_from_disk(self, params: dict) -> TextArtifact | ErrorArtifact: path = params["values"]["path"] @@ -41,10 +41,10 @@ def list_files_from_disk(self, params: dict) -> TextArtifact | ErrorArtifact: Literal( "paths", description="Relative paths to files to be loaded in the POSIX format. For example, ['foo/bar/file.txt']", - ): list[str] - } + ): list[str], + }, ), - } + }, ) def load_files_from_disk(self, params: dict) -> ListArtifact | ErrorArtifact: paths = params["values"]["paths"] @@ -70,9 +70,9 @@ def load_files_from_disk(self, params: dict) -> ListArtifact | ErrorArtifact: Literal("file_name", description="Destination file name. For example, 'baz.txt'"): str, "memory_name": str, "artifact_namespace": str, - } + }, ), - } + }, ) def save_memory_artifacts_to_disk(self, params: dict) -> ErrorArtifact | InfoArtifact: dir_name = params["values"]["dir_name"] @@ -88,7 +88,7 @@ def save_memory_artifacts_to_disk(self, params: dict) -> ErrorArtifact | InfoArt if len(list_artifact) == 0: return ErrorArtifact( - f"Failed to save memory artifacts to disk - memory named '{memory_name}' does not contain any artifacts" + f"Failed to save memory artifacts to disk - memory named '{memory_name}' does not contain any artifacts", ) for artifact in list_artifact.value: @@ -109,9 +109,9 @@ def save_memory_artifacts_to_disk(self, params: dict) -> ErrorArtifact | InfoArt description="Destination file path on disk in the POSIX format. For example, 'foo/bar/baz.txt'", ): str, "content": str, - } + }, ), - } + }, ) def save_content_to_file(self, params: dict) -> ErrorArtifact | InfoArtifact: path = params["values"]["path"] diff --git a/griptape/tools/google_cal/tool.py b/griptape/tools/google_cal/tool.py index 85f6158cd..70f685605 100644 --- a/griptape/tools/google_cal/tool.py +++ b/griptape/tools/google_cal/tool.py @@ -26,9 +26,9 @@ class GoogleCalendarClient(BaseGoogleClient): { Literal("calendar_id", description="id of the google calendar such as 'primary'"): str, Literal("max_events", description="maximum number of events to return"): int, - } + }, ), - } + }, ) def get_upcoming_events(self, params: dict) -> ListArtifact | ErrorArtifact: values = params["values"] @@ -88,19 +88,23 @@ def get_upcoming_events(self, params: dict) -> ListArtifact | ErrorArtifact: Literal("title", description="title of the event"): str, Literal("description", description="description of the event"): str, Literal( - "attendees", description="list of the email addresses of attendees using 'email' as key" + "attendees", + description="list of the email addresses of attendees using 'email' as key", ): list[str], Optional(Literal("location", description="location of the event")): str, - } + }, ), - } + }, ) def create_event(self, params: dict) -> InfoArtifact | ErrorArtifact: values = params["values"] try: service = self._build_client( - scopes=self.CREATE_EVENT_SCOPES, service_name="calendar", version="v3", owner_email=self.owner_email + scopes=self.CREATE_EVENT_SCOPES, + service_name="calendar", + version="v3", + owner_email=self.owner_email, ) event = { diff --git a/griptape/tools/google_docs/tool.py b/griptape/tools/google_docs/tool.py index 2cab05208..b3564b9b2 100644 --- a/griptape/tools/google_docs/tool.py +++ b/griptape/tools/google_docs/tool.py @@ -29,9 +29,9 @@ class GoogleDocsClient(BaseGoogleClient): "For example, 'foo/bar/baz.txt'", ): str, Literal("text", description="Text to be appended to the Google Doc."): str, - } + }, ), - } + }, ) def append_text_to_google_doc(self, params: dict) -> InfoArtifact | ErrorArtifact: values = params["values"] @@ -40,10 +40,16 @@ def append_text_to_google_doc(self, params: dict) -> InfoArtifact | ErrorArtifac try: docs_service = self._build_client( - scopes=self.DOCS_SCOPES, service_name="docs", version="v1", owner_email=self.owner_email + scopes=self.DOCS_SCOPES, + service_name="docs", + version="v1", + owner_email=self.owner_email, ) drive_service = self._build_client( - scopes=self.DRIVE_FILE_SCOPES, service_name="drive", version="v3", owner_email=self.owner_email + scopes=self.DRIVE_FILE_SCOPES, + service_name="drive", + version="v3", + owner_email=self.owner_email, ) document_id = self._convert_path_to_file_id(drive_service, file_path) @@ -77,9 +83,9 @@ def append_text_to_google_doc(self, params: dict) -> InfoArtifact | ErrorArtifac "For example, 'foo/bar/baz.txt'", ): str, Literal("text", description="Text to be prepended to the Google Doc."): str, - } + }, ), - } + }, ) def prepend_text_to_google_doc(self, params: dict) -> InfoArtifact | ErrorArtifact: values = params["values"] @@ -88,10 +94,16 @@ def prepend_text_to_google_doc(self, params: dict) -> InfoArtifact | ErrorArtifa try: docs_service = self._build_client( - scopes=self.DOCS_SCOPES, service_name="docs", version="v1", owner_email=self.owner_email + scopes=self.DOCS_SCOPES, + service_name="docs", + version="v1", + owner_email=self.owner_email, ) drive_service = self._build_client( - scopes=self.DRIVE_FILE_SCOPES, service_name="drive", version="v3", owner_email=self.owner_email + scopes=self.DRIVE_FILE_SCOPES, + service_name="drive", + version="v3", + owner_email=self.owner_email, ) document_id = self._convert_path_to_file_id(drive_service, file_path) @@ -128,9 +140,9 @@ def prepend_text_to_google_doc(self, params: dict) -> InfoArtifact | ErrorArtifa default=DEFAULT_FOLDER_PATH, description="Path of the folder where the Google doc will be created.", ): str, - } + }, ), - } + }, ) def save_content_to_google_doc(self, params: dict) -> ErrorArtifact | InfoArtifact: values = params["values"] @@ -140,10 +152,16 @@ def save_content_to_google_doc(self, params: dict) -> ErrorArtifact | InfoArtifa try: docs_service = self._build_client( - scopes=self.DOCS_SCOPES, service_name="docs", version="v1", owner_email=self.owner_email + scopes=self.DOCS_SCOPES, + service_name="docs", + version="v1", + owner_email=self.owner_email, ) drive_service = self._build_client( - scopes=self.DRIVE_FILE_SCOPES, service_name="drive", version="v3", owner_email=self.owner_email + scopes=self.DRIVE_FILE_SCOPES, + service_name="drive", + version="v3", + owner_email=self.owner_email, ) body = {"title": file_path} @@ -183,9 +201,9 @@ def save_content_to_google_doc(self, params: dict) -> ErrorArtifact | InfoArtifa description="Path of the folder where the Google Doc should be saved.", default=DEFAULT_FOLDER_PATH, ): str, - } + }, ), - } + }, ) def save_memory_artifacts_to_google_docs(self, params: dict) -> ErrorArtifact | InfoArtifact: values = params["values"] @@ -217,7 +235,10 @@ def save_memory_artifacts_to_google_docs(self, params: dict) -> ErrorArtifact | def _save_to_doc(self, params: dict) -> str: service = self._build_client( - scopes=self.DOCS_SCOPES, service_name="docs", version="v1", owner_email=self.owner_email + scopes=self.DOCS_SCOPES, + service_name="docs", + version="v1", + owner_email=self.owner_email, ) requests = [{"insertText": {"location": {"index": 1}, "text": params["content"]}}] diff --git a/griptape/tools/google_drive/tool.py b/griptape/tools/google_drive/tool.py index 427ed5e0a..d3e84f83a 100644 --- a/griptape/tools/google_drive/tool.py +++ b/griptape/tools/google_drive/tool.py @@ -41,10 +41,10 @@ class GoogleDriveClient(BaseGoogleClient): default=DEFAULT_FOLDER_PATH, description="Path of the Google Drive folder (like 'MainFolder/Subfolder1/Subfolder2') " "from which files should be listed.", - ): str - } + ): str, + }, ), - } + }, ) def list_files(self, params: dict) -> ListArtifact | ErrorArtifact: values = params["values"] @@ -54,7 +54,10 @@ def list_files(self, params: dict) -> ListArtifact | ErrorArtifact: try: service = self._build_client( - self.LIST_FILES_SCOPES, self.SERVICE_NAME, self.SERVICE_VERSION, self.owner_email + self.LIST_FILES_SCOPES, + self.SERVICE_NAME, + self.SERVICE_VERSION, + self.owner_email, ) if folder_path == self.DEFAULT_FOLDER_PATH: @@ -88,9 +91,9 @@ def list_files(self, params: dict) -> ListArtifact | ErrorArtifact: "where the file should be saved.", default=DEFAULT_FOLDER_PATH, ): str, - } + }, ), - } + }, ) def save_memory_artifacts_to_drive(self, params: dict) -> ErrorArtifact | InfoArtifact: values = params["values"] @@ -103,7 +106,10 @@ def save_memory_artifacts_to_drive(self, params: dict) -> ErrorArtifact | InfoAr if artifacts: service = self._build_client( - self.DRIVE_FILE_SCOPES, self.SERVICE_NAME, self.SERVICE_VERSION, self.owner_email + self.DRIVE_FILE_SCOPES, + self.SERVICE_NAME, + self.SERVICE_VERSION, + self.owner_email, ) if folder_path == self.DEFAULT_FOLDER_PATH: @@ -141,9 +147,9 @@ def save_memory_artifacts_to_drive(self, params: dict) -> ErrorArtifact | InfoAr "For example, 'foo/bar/baz.txt'", ): str, "content": str, - } + }, ), - } + }, ) def save_content_to_drive(self, params: dict) -> ErrorArtifact | InfoArtifact: content = params["values"]["content"] @@ -165,10 +171,10 @@ def save_content_to_drive(self, params: dict) -> ErrorArtifact | InfoArtifact: "paths", description="List of paths to files to be loaded in the POSIX format. " "For example, ['foo/bar/file1.txt', 'foo/bar/file2.txt']", - ): [str] - } + ): [str], + }, ), - } + }, ) def download_files(self, params: dict) -> ListArtifact | ErrorArtifact: from google.auth.exceptions import MalformedError @@ -179,7 +185,10 @@ def download_files(self, params: dict) -> ListArtifact | ErrorArtifact: try: service = self._build_client( - self.LIST_FILES_SCOPES, self.SERVICE_NAME, self.SERVICE_VERSION, self.owner_email + self.LIST_FILES_SCOPES, + self.SERVICE_NAME, + self.SERVICE_VERSION, + self.owner_email, ) for path in values["paths"]: @@ -230,9 +239,9 @@ def download_files(self, params: dict) -> ListArtifact | ErrorArtifact: "where the search should be performed.", default=DEFAULT_FOLDER_PATH, ): str, - } + }, ), - } + }, ) def search_files(self, params: dict) -> ListArtifact | ErrorArtifact: from google.auth.exceptions import MalformedError @@ -245,7 +254,10 @@ def search_files(self, params: dict) -> ListArtifact | ErrorArtifact: try: service = self._build_client( - self.LIST_FILES_SCOPES, self.SERVICE_NAME, self.SERVICE_VERSION, self.owner_email + self.LIST_FILES_SCOPES, + self.SERVICE_NAME, + self.SERVICE_VERSION, + self.owner_email, ) folder_id = None @@ -296,9 +308,9 @@ def search_files(self, params: dict) -> ListArtifact | ErrorArtifact: "writer", # pyright: ignore [reportArgumentType] "commenter", # pyright: ignore [reportArgumentType] ), - } + }, ), - } + }, ) def share_file(self, params: dict) -> InfoArtifact | ErrorArtifact: from google.auth.exceptions import MalformedError @@ -311,7 +323,10 @@ def share_file(self, params: dict) -> InfoArtifact | ErrorArtifact: try: service = self._build_client( - scopes=self.DRIVE_AUTH_SCOPES, service_name="drive", version="v3", owner_email=self.owner_email + scopes=self.DRIVE_AUTH_SCOPES, + service_name="drive", + version="v3", + owner_email=self.owner_email, ) if file_path.lower() == self.DEFAULT_FOLDER_PATH: @@ -322,7 +337,9 @@ def share_file(self, params: dict) -> InfoArtifact | ErrorArtifact: if file_id: batch_update_permission_request_body = {"role": role, "type": "user", "emailAddress": email_address} request = service.permissions().create( - fileId=file_id, body=batch_update_permission_request_body, fields="id" + fileId=file_id, + body=batch_update_permission_request_body, + fields="id", ) request.execute() return InfoArtifact(f"File at {file_path} shared with {email_address} as a {role}") @@ -336,7 +353,10 @@ def share_file(self, params: dict) -> InfoArtifact | ErrorArtifact: return ErrorArtifact(f"error sharing file: {e}") def _save_to_drive( - self, filename: str, value: Any, parent_folder_id: Optional[str] = None + self, + filename: str, + value: Any, + parent_folder_id: Optional[str] = None, ) -> InfoArtifact | ErrorArtifact: from googleapiclient.http import MediaIoBaseUpload # pyright: ignore[reportMissingImports] diff --git a/griptape/tools/google_gmail/tool.py b/griptape/tools/google_gmail/tool.py index 137f2584b..853b8850f 100644 --- a/griptape/tools/google_gmail/tool.py +++ b/griptape/tools/google_gmail/tool.py @@ -26,16 +26,19 @@ class GoogleGmailClient(BaseGoogleClient): Literal("to", description="email address which to send to"): str, Literal("subject", description="subject of the email"): str, Literal("body", description="body of the email"): str, - } + }, ), - } + }, ) def create_draft_email(self, params: dict) -> InfoArtifact | ErrorArtifact: values = params["values"] try: service = self._build_client( - scopes=self.CREATE_DRAFT_EMAIL_SCOPES, service_name="gmail", version="v1", owner_email=self.owner_email + scopes=self.CREATE_DRAFT_EMAIL_SCOPES, + service_name="gmail", + version="v1", + owner_email=self.owner_email, ) message = EmailMessage() diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 438d09aa0..0c544524d 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -27,9 +27,14 @@ class GriptapeCloudKnowledgeBaseClient(BaseGriptapeCloudClient): config={ "description": "Can be used to search a knowledge base with the following description: {{ _self._get_knowledge_base_description() }}", "schema": Schema( - {Literal("query", description="A natural language search query to run against the knowledge base"): str} + { + Literal( + "query", + description="A natural language search query to run against the knowledge base", + ): str, + }, ), - } + }, ) def query(self, params: dict) -> TextArtifact | ErrorArtifact: from requests import exceptions, post @@ -59,7 +64,7 @@ def _get_knowledge_base_description(self) -> str: return response_body["description"] else: raise ValueError( - f"No description found for Knowledge Base {self.knowledge_base_id}. Please set a description, or manually set the `GriptapeCloudKnowledgeBaseClient.description` attribute." + f"No description found for Knowledge Base {self.knowledge_base_id}. Please set a description, or manually set the `GriptapeCloudKnowledgeBaseClient.description` attribute.", ) else: raise ValueError(f"Error accessing Knowledge Base {self.knowledge_base_id}.") diff --git a/griptape/tools/image_query_client/tool.py b/griptape/tools/image_query_client/tool.py index aeaa3e4b2..1b8cea534 100644 --- a/griptape/tools/image_query_client/tool.py +++ b/griptape/tools/image_query_client/tool.py @@ -30,9 +30,9 @@ class ImageQueryClient(BaseTool): description="A detailed question to be answered using the contents of the provided images.", ): str, Literal("image_paths", description="The paths to an image files on disk."): list[str], - } + }, ), - } + }, ) def query_image_from_disk(self, params: dict) -> TextArtifact | ErrorArtifact: query = params["values"]["query"] @@ -55,12 +55,12 @@ def query_image_from_disk(self, params: dict) -> TextArtifact | ErrorArtifact: description="A detailed question to be answered using the contents of the provided images.", ): str, Literal("image_artifacts", description="Image artifact memory references."): [ - {"image_artifact_namespace": str, "image_artifact_name": str} + {"image_artifact_namespace": str, "image_artifact_name": str}, ], "memory_name": str, - } + }, ), - } + }, ) def query_images_from_memory(self, params: dict[str, Any]) -> TextArtifact | ErrorArtifact: query = params["values"]["query"] diff --git a/griptape/tools/inpainting_image_generation_client/tool.py b/griptape/tools/inpainting_image_generation_client/tool.py index 7c57e6f08..ff60dd975 100644 --- a/griptape/tools/inpainting_image_generation_client/tool.py +++ b/griptape/tools/inpainting_image_generation_client/tool.py @@ -47,9 +47,9 @@ class InpaintingImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): description="The path to an image file to be used as a base to generate variations from.", ): str, Literal("mask_file", description="The path to mask image file."): str, - } + }, ), - } + }, ) def image_inpainting_from_file(self, params: dict[str, Any]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] @@ -61,7 +61,10 @@ def image_inpainting_from_file(self, params: dict[str, Any]) -> ImageArtifact | mask_artifact = self.image_loader.load(mask_file) output_artifact = self.engine.run( - prompts=prompts, negative_prompts=negative_prompts, image=input_artifact, mask=mask_artifact + prompts=prompts, + negative_prompts=negative_prompts, + image=input_artifact, + mask=mask_artifact, ) if self.output_dir or self.output_file: @@ -87,9 +90,9 @@ def image_inpainting_from_file(self, params: dict[str, Any]) -> ImageArtifact | "image_artifact_name": str, "mask_artifact_namespace": str, "mask_artifact_name": str, - } + }, ), - } + }, ) def image_inpainting_from_memory(self, params: dict[str, Any]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] @@ -105,16 +108,25 @@ def image_inpainting_from_memory(self, params: dict[str, Any]) -> ImageArtifact try: image_artifact = load_artifact_from_memory( - memory, image_artifact_namespace, image_artifact_name, ImageArtifact + memory, + image_artifact_namespace, + image_artifact_name, + ImageArtifact, ) mask_artifact = load_artifact_from_memory( - memory, mask_artifact_namespace, mask_artifact_name, ImageArtifact + memory, + mask_artifact_namespace, + mask_artifact_name, + ImageArtifact, ) except ValueError as e: return ErrorArtifact(str(e)) return self._generate_inpainting( - prompts, negative_prompts, cast(ImageArtifact, image_artifact), cast(ImageArtifact, mask_artifact) + prompts, + negative_prompts, + cast(ImageArtifact, image_artifact), + cast(ImageArtifact, mask_artifact), ) def _generate_inpainting( @@ -125,7 +137,10 @@ def _generate_inpainting( mask_artifact: ImageArtifact, ) -> ImageArtifact: output_artifact = self.engine.run( - prompts=prompts, negative_prompts=negative_prompts, image=image_artifact, mask=mask_artifact + prompts=prompts, + negative_prompts=negative_prompts, + image=image_artifact, + mask=mask_artifact, ) if self.output_dir or self.output_file: diff --git a/griptape/tools/openweather_client/tool.py b/griptape/tools/openweather_client/tool.py index 21b80c6f0..d15bbc87a 100644 --- a/griptape/tools/openweather_client/tool.py +++ b/griptape/tools/openweather_client/tool.py @@ -82,10 +82,10 @@ class OpenWeatherClient(BaseTool): "For US cities, use the format 'city_name, state_code'. " "For non-US cities, use 'city_name, country_code'. " "For cities without specifying state or country, simply use 'city_name'.", - ): str - } + ): str, + }, ), - } + }, ) def get_coordinates_by_location(self, params: dict) -> InfoArtifact | ErrorArtifact: location = params["values"].get("location") @@ -109,7 +109,7 @@ def _fetch_coordinates(self, location: str) -> Optional[tuple[float, Optional[fl return data[0]["lat"], data[0]["lon"] else: logging.error( - f"Error fetching coordinates. HTTP Status Code: {response.status_code}. Response: {response.text}" + f"Error fetching coordinates. HTTP Status Code: {response.status_code}. Response: {response.text}", ) except Exception as e: logging.error(f"Error fetching coordinates: {e}") @@ -120,7 +120,7 @@ def _fetch_coordinates(self, location: str) -> Optional[tuple[float, Optional[fl "description": "Can be used to fetch current weather data for a given location. " "Temperatures are returned in {{ _self.units }} by default.", "schema": Schema({Literal("location", description="Location to fetch weather data for."): str}), - } + }, ) def get_current_weather_by_location(self, params: dict) -> ListArtifact | TextArtifact | ErrorArtifact: location = params["values"].get("location") @@ -143,7 +143,7 @@ def get_current_weather_by_location(self, params: dict) -> ListArtifact | TextAr "description": "Can be used to fetch hourly forecast for a given location up to 48 hours ahead. " "Temperatures are returned in {{ _self.units }} by default.", "schema": Schema({Literal("location", description="Location to fetch hourly forecast for."): str}), - } + }, ) def get_hourly_forecast_by_location(self, params: dict) -> ListArtifact | TextArtifact | ErrorArtifact: location = params["values"].get("location") @@ -166,7 +166,7 @@ def get_hourly_forecast_by_location(self, params: dict) -> ListArtifact | TextAr "description": "Can be used to fetch daily forecast for a given location up to 8 days ahead. " "Temperatures are returned in {{ _self.units }} by default.", "schema": Schema({Literal("location", description="Location to fetch daily forecast for."): str}), - } + }, ) def get_daily_forecast_by_location(self, params: dict) -> ListArtifact | TextArtifact | ErrorArtifact: location = params["values"].get("location") diff --git a/griptape/tools/outpainting_image_generation_client/tool.py b/griptape/tools/outpainting_image_generation_client/tool.py index 0e355b1dc..e11bb8cd8 100644 --- a/griptape/tools/outpainting_image_generation_client/tool.py +++ b/griptape/tools/outpainting_image_generation_client/tool.py @@ -47,9 +47,9 @@ class OutpaintingImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): description="The path to an image file to be used as a base to generate variations from.", ): str, Literal("mask_file", description="The path to mask image file."): str, - } + }, ), - } + }, ) def image_outpainting_from_file(self, params: dict[str, Any]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] @@ -78,9 +78,9 @@ def image_outpainting_from_file(self, params: dict[str, Any]) -> ImageArtifact | "memory_name": str, "image_artifact_namespace": str, "mask_artifact_namespace": str, - } + }, ), - } + }, ) def image_outpainting_from_memory(self, params: dict[str, Any]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] @@ -96,16 +96,25 @@ def image_outpainting_from_memory(self, params: dict[str, Any]) -> ImageArtifact try: image_artifact = load_artifact_from_memory( - memory, image_artifact_namespace, image_artifact_name, ImageArtifact + memory, + image_artifact_namespace, + image_artifact_name, + ImageArtifact, ) mask_artifact = load_artifact_from_memory( - memory, mask_artifact_namespace, mask_artifact_name, ImageArtifact + memory, + mask_artifact_namespace, + mask_artifact_name, + ImageArtifact, ) except ValueError as e: return ErrorArtifact(str(e)) return self._generate_outpainting( - prompts, negative_prompts, cast(ImageArtifact, image_artifact), cast(ImageArtifact, mask_artifact) + prompts, + negative_prompts, + cast(ImageArtifact, image_artifact), + cast(ImageArtifact, mask_artifact), ) def _generate_outpainting( @@ -116,7 +125,10 @@ def _generate_outpainting( mask_artifact: ImageArtifact, ): output_artifact = self.engine.run( - prompts=prompts, negative_prompts=negative_prompts, image=image_artifact, mask=mask_artifact + prompts=prompts, + negative_prompts=negative_prompts, + image=image_artifact, + mask=mask_artifact, ) if self.output_dir or self.output_file: diff --git a/griptape/tools/prompt_image_generation_client/tool.py b/griptape/tools/prompt_image_generation_client/tool.py index 17e2f6768..1373d5523 100644 --- a/griptape/tools/prompt_image_generation_client/tool.py +++ b/griptape/tools/prompt_image_generation_client/tool.py @@ -34,10 +34,10 @@ class PromptImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): Literal( "prompts", description="A detailed list of features and descriptions to include in the generated image.", - ): list[str] - } + ): list[str], + }, ), - } + }, ) def generate_image(self, params: dict[str, dict[str, list[str]]]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] diff --git a/griptape/tools/rag_client/tool.py b/griptape/tools/rag_client/tool.py index afc1b9d06..bbdef8159 100644 --- a/griptape/tools/rag_client/tool.py +++ b/griptape/tools/rag_client/tool.py @@ -29,7 +29,7 @@ class RagClient(BaseTool): config={ "description": "{{ _self.description }}", "schema": Schema({Literal("query", description="A natural language search query"): str}), - } + }, ) def search(self, params: dict) -> BaseArtifact: query = params["values"]["query"] diff --git a/griptape/tools/rest_api_client/tool.py b/griptape/tools/rest_api_client/tool.py index dbd294cd9..6d359e20e 100644 --- a/griptape/tools/rest_api_client/tool.py +++ b/griptape/tools/rest_api_client/tool.py @@ -49,10 +49,10 @@ def full_url(self) -> str: This rest api has the following description: {{ _self.description }} {% if _self.request_body_schema %}The request body must follow this JSON schema: {{ _self.request_body_schema }}{% endif %} {% if _self.response_body_schema %}The response body must follow this JSON schema: {{ _self.response_body_schema }}{% endif %} - """ + """, ), "schema": Schema({Literal("body", description="The request body."): dict}), - } + }, ) def put(self, params: dict) -> BaseArtifact: from requests import exceptions, put @@ -79,15 +79,15 @@ def put(self, params: dict) -> BaseArtifact: {% if _self.request_path_parameters %}The request path parameters must follow this JSON schema: {{ _self.request_path_params_schema }}{% endif %} {% if _self.request_body_schema %}The request body must follow this JSON schema: {{ _self.request_body_schema }}{% endif %} {% if _self.response_body_schema %}The response body must follow this JSON schema: {{ _self.response_body_schema }}{% endif %} - """ + """, ), "schema": Schema( { Literal("path_params", description="The request path parameters."): list[str], Literal("body", description="The request body."): dict, - } + }, ), - } + }, ) def patch(self, params: dict) -> BaseArtifact: from requests import exceptions, patch @@ -113,10 +113,10 @@ def patch(self, params: dict) -> BaseArtifact: This rest api has the following description: {{ _self.description }} {% if _self.request_body_schema %}The request body must follow this JSON schema: {{ _self.request_body_schema }}{% endif %} {% if _self.response_body_schema %}The response body must follow this JSON schema: {{ _self.response_body_schema }}{% endif %} - """ + """, ), "schema": Schema({Literal("body", description="The request body."): dict}), - } + }, ) def post(self, params: dict) -> BaseArtifact: from requests import exceptions, post @@ -142,17 +142,17 @@ def post(self, params: dict) -> BaseArtifact: {% if _self.request_path_parameters %}The request path parameters must follow this JSON schema: {{ _self.request_path_params_schema }}{% endif %} {% if _self.request_query_parameters %}The request query parameters must follow this JSON schema: {{ _self.request_path_params_schema }}{% endif %} {% if _self.response_body_schema %}The response body must follow this JSON schema: {{ _self.response_body_schema }}{% endif %} - """ + """, ), "schema": schema.Optional( Schema( { schema.Optional(Literal("query_params", description="The request query parameters.")): dict, schema.Optional(Literal("path_params", description="The request path parameters.")): list[str], - } - ) + }, + ), ), - } + }, ) def get(self, params: dict) -> BaseArtifact: from requests import exceptions, get @@ -182,15 +182,15 @@ def get(self, params: dict) -> BaseArtifact: This rest api has the following description: {{ _self.description }} {% if _self.request_path_parameters %}The request path parameters must follow this JSON schema: {{ _self.request_path_params_schema }}{% endif %} {% if _self.request_query_parameters %}The request query parameters must follow this JSON schema: {{ _self.request_path_params_schema }}{% endif %} - """ + """, ), "schema": Schema( { schema.Optional(Literal("query_params", description="The request query parameters.")): dict, schema.Optional(Literal("path_params", description="The request path parameters.")): list[str], - } + }, ), - } + }, ) def delete(self, params: dict) -> BaseArtifact: from requests import delete, exceptions diff --git a/griptape/tools/sql_client/tool.py b/griptape/tools/sql_client/tool.py index 93c69c51b..2de598c6b 100644 --- a/griptape/tools/sql_client/tool.py +++ b/griptape/tools/sql_client/tool.py @@ -41,7 +41,7 @@ def table_schema(self) -> Optional[str]: "{{ _self.table_name }} schema: {{ _self.table_schema }}\n" "{% if _self.table_description %}{{ _self.table_name }} description: {{ _self.table_description }}{% endif %}", "schema": Schema({"sql_query": str}), - } + }, ) def execute_query(self, params: dict) -> ListArtifact | InfoArtifact | ErrorArtifact: try: diff --git a/griptape/tools/structure_run_client/tool.py b/griptape/tools/structure_run_client/tool.py index 0a1cc223b..f4f6c3786 100644 --- a/griptape/tools/structure_run_client/tool.py +++ b/griptape/tools/structure_run_client/tool.py @@ -29,9 +29,9 @@ class StructureRunClient(BaseTool): config={ "description": "Can be used to run a Griptape Structure with the following description: {{ self.description }}", "schema": Schema( - {Literal("args", description="A list of string arguments to submit to the Structure Run"): list[str]} + {Literal("args", description="A list of string arguments to submit to the Structure Run"): list[str]}, ), - } + }, ) def run_structure(self, params: dict) -> BaseArtifact: args: list[str] = params["values"]["args"] diff --git a/griptape/tools/task_memory_client/tool.py b/griptape/tools/task_memory_client/tool.py index 406f50fed..160a54d85 100644 --- a/griptape/tools/task_memory_client/tool.py +++ b/griptape/tools/task_memory_client/tool.py @@ -14,7 +14,7 @@ class TaskMemoryClient(BaseTool): config={ "description": "Can be used to summarize memory content", "schema": Schema({"memory_name": str, "artifact_namespace": str}), - } + }, ) def summarize(self, params: dict) -> TextArtifact | InfoArtifact | ErrorArtifact: memory = self.find_input_memory(params["values"]["memory_name"]) @@ -37,9 +37,9 @@ def summarize(self, params: dict) -> TextArtifact | InfoArtifact | ErrorArtifact description="A natural language search query in the form of a question with enough " "contextual information for another person to understand what the query is about", ): str, - } + }, ), - } + }, ) def query(self, params: dict) -> BaseArtifact: memory = self.find_input_memory(params["values"]["memory_name"]) diff --git a/griptape/tools/text_to_speech_client/tool.py b/griptape/tools/text_to_speech_client/tool.py index 9649279be..295641fd3 100644 --- a/griptape/tools/text_to_speech_client/tool.py +++ b/griptape/tools/text_to_speech_client/tool.py @@ -30,7 +30,7 @@ class TextToSpeechClient(BlobArtifactFileOutputMixin, BaseTool): config={ "description": "Can be used to generate speech from the provided input text.", "schema": Schema({Literal("text", description="The literal text to be converted to speech."): str}), - } + }, ) def text_to_speech(self, params: dict[str, Any]) -> AudioArtifact | ErrorArtifact: text = params["values"]["text"] diff --git a/griptape/tools/variation_image_generation_client/tool.py b/griptape/tools/variation_image_generation_client/tool.py index c1ab91896..e82561c59 100644 --- a/griptape/tools/variation_image_generation_client/tool.py +++ b/griptape/tools/variation_image_generation_client/tool.py @@ -46,9 +46,9 @@ class VariationImageGenerationClient(BlobArtifactFileOutputMixin, BaseTool): "image_file", description="The path to an image file to be used as a base to generate variations from.", ): str, - } + }, ), - } + }, ) def image_variation_from_file(self, params: dict[str, Any]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] @@ -77,9 +77,9 @@ def image_variation_from_file(self, params: dict[str, Any]) -> ImageArtifact | E "memory_name": str, "artifact_namespace": str, "artifact_name": str, - } + }, ), - } + }, ) def image_variation_from_memory(self, params: dict[str, Any]) -> ImageArtifact | ErrorArtifact: prompts = params["values"]["prompts"] diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index ef831e508..a0c638eef 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -30,7 +30,7 @@ class VectorStoreClient(BaseTool): vector_store_driver: BaseVectorStoreDriver = field() query_params: dict[str, Any] = field(factory=dict) process_query_output_fn: Callable[[list[BaseVectorStoreDriver.Entry]], BaseArtifact] = field( - default=Factory(lambda: lambda es: ListArtifact([e.to_artifact() for e in es])) + default=Factory(lambda: lambda es: ListArtifact([e.to_artifact() for e in es])), ) @activity( @@ -39,11 +39,12 @@ class VectorStoreClient(BaseTool): "schema": Schema( { Literal( - "query", description="A natural language search query to run against the vector database" - ): str - } + "query", + description="A natural language search query to run against the vector database", + ): str, + }, ), - } + }, ) def search(self, params: dict) -> BaseArtifact: query = params["values"]["query"] diff --git a/griptape/tools/web_scraper/tool.py b/griptape/tools/web_scraper/tool.py index a72378bb2..782e85d37 100644 --- a/griptape/tools/web_scraper/tool.py +++ b/griptape/tools/web_scraper/tool.py @@ -17,7 +17,7 @@ class WebScraper(BaseTool): config={ "description": "Can be used to browse a web page and load its content", "schema": Schema({Literal("url", description="Valid HTTP URL"): str}), - } + }, ) def get_content(self, params: dict) -> ListArtifact | ErrorArtifact: url = params["values"]["url"] diff --git a/griptape/tools/web_search/tool.py b/griptape/tools/web_search/tool.py index 5a3360077..8a1821a13 100644 --- a/griptape/tools/web_search/tool.py +++ b/griptape/tools/web_search/tool.py @@ -25,10 +25,10 @@ class WebSearch(BaseTool): Literal( "query", description="Search engine request that returns a list of pages with titles, descriptions, and URLs", - ): str - } + ): str, + }, ), - } + }, ) def search(self, props: dict) -> ListArtifact | ErrorArtifact: query = props["values"]["query"] diff --git a/griptape/utils/chat.py b/griptape/utils/chat.py index 032938706..e98eeaa4d 100644 --- a/griptape/utils/chat.py +++ b/griptape/utils/chat.py @@ -20,7 +20,8 @@ class Chat: prompt_prefix: str = field(default="User: ", kw_only=True) response_prefix: str = field(default="Assistant: ", kw_only=True) output_fn: Callable[[str], None] = field( - default=Factory(lambda self: self.default_output_fn, takes_self=True), kw_only=True + default=Factory(lambda self: self.default_output_fn, takes_self=True), + kw_only=True, ) def default_output_fn(self, text: str) -> None: diff --git a/griptape/utils/file_utils.py b/griptape/utils/file_utils.py index 01dd1318a..f730034d3 100644 --- a/griptape/utils/file_utils.py +++ b/griptape/utils/file_utils.py @@ -34,5 +34,5 @@ def load_files(paths: list[str], futures_executor: Optional[futures.ThreadPoolEx with futures_executor as executor: return utils.execute_futures_dict( - {utils.str_to_hash(str(path)): executor.submit(load_file, path) for path in paths} + {utils.str_to_hash(str(path)): executor.submit(load_file, path) for path in paths}, ) diff --git a/griptape/utils/load_artifact_from_memory.py b/griptape/utils/load_artifact_from_memory.py index af11b8ae8..a45a41dbd 100644 --- a/griptape/utils/load_artifact_from_memory.py +++ b/griptape/utils/load_artifact_from_memory.py @@ -3,7 +3,10 @@ def load_artifact_from_memory( - memory: TaskMemory, artifact_namespace: str, artifact_name: str, artifact_type: type + memory: TaskMemory, + artifact_namespace: str, + artifact_name: str, + artifact_type: type, ) -> BaseArtifact: if memory is None: raise ValueError("memory not found") diff --git a/griptape/utils/stream.py b/griptape/utils/stream.py index 64f94e943..fe0cf50d7 100644 --- a/griptape/utils/stream.py +++ b/griptape/utils/stream.py @@ -61,7 +61,8 @@ def event_handler(event: BaseEvent): self._event_queue.put(event) stream_event_listener = EventListener( - handler=event_handler, event_types=[CompletionChunkEvent, FinishPromptEvent, FinishStructureRunEvent] + handler=event_handler, + event_types=[CompletionChunkEvent, FinishPromptEvent, FinishStructureRunEvent], ) self.structure.add_event_listener(stream_event_listener) diff --git a/pyproject.toml b/pyproject.toml index a1ed38836..a03e2ac2d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -197,9 +197,6 @@ pymdown-extensions = "^10.3" [tool.ruff] line-length = 120 -[tool.ruff.format] -skip-magic-trailing-comma = true - [tool.ruff.lint] select = [ "E", # pycodestyle @@ -214,7 +211,8 @@ select = [ "D", # pydocstyle "PGH", # pygrep-hooks "I", # isort - "FA" # flake8-future-annotations + "FA", # flake8-future-annotations + "COM" # flake8-commas ] ignore = [ "UP007", # non-pep604-annotation @@ -230,6 +228,7 @@ ignore = [ "D105", # undocumented-magic-method "D106", # undocumented-public-nested-class "D107", # undocumented-public-init + "COM812" # missing-trailing-comma -- See https://github.com/astral-sh/ruff/issues/9216 ] [tool.ruff.lint.pydocstyle] convention = "google" From 9371aab2e550cfc07a04d4df87ffd61248d62bb7 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 15 Jul 2024 11:01:22 -0700 Subject: [PATCH 68/87] Enable pycodestyle-warnings ruff rule (#978) --- griptape/tokenizers/openai_tokenizer.py | 6 +++--- pyproject.toml | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/griptape/tokenizers/openai_tokenizer.py b/griptape/tokenizers/openai_tokenizer.py index 9cbbd6a03..b839109fa 100644 --- a/griptape/tokenizers/openai_tokenizer.py +++ b/griptape/tokenizers/openai_tokenizer.py @@ -120,9 +120,9 @@ def count_tokens(self, text: str | list[dict], model: Optional[str] = None) -> i return self.count_tokens(text, model="gpt-4-0613") else: raise NotImplementedError( - f"""token_count() is not implemented for model {model}. - See https://github.com/openai/openai-python/blob/main/chatml.md for - information on how messages are converted to tokens.""", + f"token_count() is not implemented for model {model}. " + "See https://github.com/openai/openai-python/blob/main/chatml.md for " + "information on how messages are converted to tokens." ) num_tokens = 0 diff --git a/pyproject.toml b/pyproject.toml index a03e2ac2d..75789369c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -199,7 +199,8 @@ line-length = 120 [tool.ruff.lint] select = [ - "E", # pycodestyle + "E", # pycodestyle-errors + "W", # pycodestyle-warnings "F", # Pyflakes "UP", # pyupgrade "B", # flake8-bugbear From 71ba8520e37636a5d07e6c4b70fdf03cac033d37 Mon Sep 17 00:00:00 2001 From: Emily Danielson <2302515+emjay07@users.noreply.github.com> Date: Mon, 15 Jul 2024 12:02:28 -0700 Subject: [PATCH 69/87] updating docs to use 35-turbo instead of 35-turbo-16k (#980) --- .github/workflows/docs-integration-tests.yml | 1 + docs/griptape-framework/drivers/prompt-drivers.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index cd21ad1ac..241c4a2ef 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -90,6 +90,7 @@ jobs: AZURE_OPENAI_ENDPOINT_3: ${{ secrets.INTEG_AZURE_OPENAI_ENDPOINT_3 }} AZURE_OPENAI_API_KEY_3: ${{ secrets.INTEG_AZURE_OPENAI_API_KEY_3 }} AZURE_OPENAI_35_TURBO_16K_DEPLOYMENT_ID: ${{ secrets.INTEG_OPENAI_35_TURBO_16K_DEPLOYMENT_ID }} + AZURE_OPENAI_35_TURBO_DEPLOYMENT_ID: ${{ secrets.INTEG_OPENAI_35_TURBO_DEPLOYMENT_ID }} AZURE_OPENAI_DAVINCI_DEPLOYMENT_ID: ${{ secrets.INTEG_OPENAI_DAVINCI_DEPLOYMENT_ID }} AZURE_OPENAI_4_DEPLOYMENT_ID: ${{ secrets.INTEG_OPENAI_4_DEPLOYMENT_ID }} AZURE_OPENAI_4_32K_DEPLOYMENT_ID: ${{ secrets.INTEG_OPENAI_4_32K_DEPLOYMENT_ID }} diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index b9fc7f161..bc6142d3d 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -142,8 +142,8 @@ agent = Agent( config=StructureConfig( prompt_driver=AzureOpenAiChatPromptDriver( api_key=os.environ["AZURE_OPENAI_API_KEY_1"], - model="gpt-3.5-turbo-16k", - azure_deployment=os.environ["AZURE_OPENAI_35_TURBO_16K_DEPLOYMENT_ID"], + model="gpt-3.5-turbo", + azure_deployment=os.environ["AZURE_OPENAI_35_TURBO_DEPLOYMENT_ID"], azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT_1"], ) ), From 2ee57a67ec3346e1c96fe1c82c3058a772a5e4dd Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 15 Jul 2024 12:32:39 -0700 Subject: [PATCH 70/87] Enable flake8-comprehensions ruff rule (#977) --- griptape/artifacts/base_artifact.py | 2 +- griptape/drivers/file_manager/base_file_manager_driver.py | 2 +- griptape/drivers/prompt/google_prompt_driver.py | 4 ++-- griptape/drivers/sql/snowflake_sql_driver.py | 2 +- griptape/drivers/sql/sql_driver.py | 2 +- griptape/tasks/actions_subtask.py | 2 +- griptape/tasks/image_query_task.py | 2 +- pyproject.toml | 3 ++- 8 files changed, 10 insertions(+), 9 deletions(-) diff --git a/griptape/artifacts/base_artifact.py b/griptape/artifacts/base_artifact.py index 249ae48c8..d1e0d34f4 100644 --- a/griptape/artifacts/base_artifact.py +++ b/griptape/artifacts/base_artifact.py @@ -36,7 +36,7 @@ def value_to_bytes(cls, value: Any) -> bytes: def value_to_dict(cls, value: Any) -> dict: dict_value = value if isinstance(value, dict) else json.loads(value) - return {k: v for k, v in dict_value.items()} + return dict(dict_value.items()) def to_text(self) -> str: return str(self.value) diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index 5fdb84b8f..db7f64438 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -43,7 +43,7 @@ class BaseFileManagerDriver(ABC): def list_files(self, path: str) -> TextArtifact | ErrorArtifact: try: entries = self.try_list_files(path) - return TextArtifact("\n".join([e for e in entries])) + return TextArtifact("\n".join(list(entries))) except FileNotFoundError: return ErrorArtifact("Path not found") except NotADirectoryError: diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 33c5a9985..c85835826 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -230,7 +230,7 @@ def __to_prompt_stack_message_content(self, content: Part) -> BaseMessageContent name, path = ToolAction.from_native_tool_name(function_call.name) - args = {k: v for k, v in function_call.args.items()} + args = dict(function_call.args.items()) return ActionCallMessageContent( artifact=ActionArtifact(value=ToolAction(tag=function_call.name, name=name, path=path, input=args)), ) @@ -245,7 +245,7 @@ def __to_prompt_stack_delta_message_content(self, content: Part) -> BaseDeltaMes name, path = ToolAction.from_native_tool_name(function_call.name) - args = {k: v for k, v in function_call.args.items()} + args = dict(function_call.args.items()) return ActionCallDeltaMessageContent( tag=function_call.name, name=name, diff --git a/griptape/drivers/sql/snowflake_sql_driver.py b/griptape/drivers/sql/snowflake_sql_driver.py index a2d3eaead..6fa75bb1c 100644 --- a/griptape/drivers/sql/snowflake_sql_driver.py +++ b/griptape/drivers/sql/snowflake_sql_driver.py @@ -59,7 +59,7 @@ def execute_query_raw(self, query: str) -> Optional[list[dict[str, Any]]]: if results is not None: if results.returns_rows: - return [{column: value for column, value in result.items()} for result in results] + return [dict(result.items()) for result in results] else: return None else: diff --git a/griptape/drivers/sql/sql_driver.py b/griptape/drivers/sql/sql_driver.py index d3da01e2e..5a3a4f5b2 100644 --- a/griptape/drivers/sql/sql_driver.py +++ b/griptape/drivers/sql/sql_driver.py @@ -38,7 +38,7 @@ def execute_query_raw(self, query: str) -> Optional[list[dict[str, Optional[Any] if results is not None: if results.returns_rows: - return [{column: value for column, value in result.items()} for result in results] + return [dict(result.items()) for result in results] else: return None else: diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index 3a44dc3e6..66ec9c0b0 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -128,7 +128,7 @@ def execute_actions(self, actions: list[ToolAction]) -> list[tuple[str, BaseArti with self.futures_executor_fn() as executor: results = utils.execute_futures_dict({a.tag: executor.submit(self.execute_action, a) for a in actions}) - return [r for r in results.values()] + return list(results.values()) def execute_action(self, action: ToolAction) -> tuple[str, BaseArtifact]: if action.tool is not None: diff --git a/griptape/tasks/image_query_task.py b/griptape/tasks/image_query_task.py index 527729b94..60a1c89c8 100644 --- a/griptape/tasks/image_query_task.py +++ b/griptape/tasks/image_query_task.py @@ -78,7 +78,7 @@ def image_query_engine(self, value: ImageQueryEngine) -> None: def run(self) -> TextArtifact: query = self.input.value[0] - if all([isinstance(input, ImageArtifact) for input in self.input.value[1:]]): + if all(isinstance(input, ImageArtifact) for input in self.input.value[1:]): image_artifacts = [input for input in self.input.value[1:] if isinstance(input, ImageArtifact)] else: raise ValueError("All inputs after the query must be ImageArtifacts.") diff --git a/pyproject.toml b/pyproject.toml index 75789369c..a6b35bd7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -213,7 +213,8 @@ select = [ "PGH", # pygrep-hooks "I", # isort "FA", # flake8-future-annotations - "COM" # flake8-commas + "COM", # flake8-commas + "C4", # flake8-comprehensions ] ignore = [ "UP007", # non-pep604-annotation From 67a913b983f7de2722227784df2c7269d2e9174c Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 15 Jul 2024 13:36:06 -0700 Subject: [PATCH 71/87] Fully enable flake8-tidy-imports, flake8-print, mccabe (#976) --- pyproject.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a6b35bd7d..0c0d28d3f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -205,9 +205,9 @@ select = [ "UP", # pyupgrade "B", # flake8-bugbear "SIM", # flake8-simplify - "TID251", # banned-api - "T201", # print - "C901", # complex-structure + "TID", # flake8-tidy-imports + "T20", # flake8-print + "C90", # mccabe "TCH", # flake8-type-checking "D", # pydocstyle "PGH", # pygrep-hooks From 5c4b3a87dab8732e24eae7835e7cd64303a3ee47 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Mon, 15 Jul 2024 13:57:03 -0700 Subject: [PATCH 72/87] Add flake8-annotations ruff rule (#975) --- griptape/artifacts/list_artifact.py | 4 ++-- griptape/chunkers/base_chunker.py | 4 ++-- griptape/common/prompt_stack/messages/message.py | 2 +- .../griptape_cloud_event_listener_driver.py | 4 ++-- .../amazon_s3_file_manager_driver.py | 6 +++--- .../file_manager/base_file_manager_driver.py | 2 +- .../file_manager/local_file_manager_driver.py | 6 +++--- .../image_query/anthropic_image_query_driver.py | 2 +- .../amazon_sagemaker_jumpstart_prompt_driver.py | 4 ++-- griptape/drivers/prompt/base_prompt_driver.py | 4 +++- .../drivers/sql/amazon_redshift_sql_driver.py | 10 +++++----- griptape/drivers/sql/snowflake_sql_driver.py | 6 +++--- ...e_cloud_knowledge_base_vector_store_driver.py | 4 ++-- .../drivers/vector/local_vector_store_driver.py | 6 +++--- .../drivers/vector/marqo_vector_store_driver.py | 4 ++-- .../vector/mongodb_atlas_vector_store_driver.py | 2 +- .../vector/opensearch_vector_store_driver.py | 6 +++--- .../vector/pgvector_vector_store_driver.py | 10 +++++----- .../vector/pinecone_vector_store_driver.py | 6 +++--- .../drivers/vector/redis_vector_store_driver.py | 4 ++-- .../markdownify_web_scraper_driver.py | 6 +++--- .../engines/extraction/base_extraction_engine.py | 4 ++-- .../engines/summary/prompt_summary_engine.py | 4 ++-- griptape/exceptions/dummy_exception.py | 2 +- griptape/loaders/email_loader.py | 2 +- .../memory/task/storage/text_artifact_storage.py | 4 ++-- griptape/memory/task/task_memory.py | 6 +++--- griptape/mixins/activity_mixin.py | 8 ++++---- .../mixins/media_artifact_file_output_mixin.py | 6 +++--- griptape/mixins/rule_mixin.py | 6 +++--- griptape/schemas/base_schema.py | 4 ++-- griptape/schemas/bytes_field.py | 7 ++++--- griptape/schemas/polymorphic_schema.py | 16 ++++++++-------- griptape/structures/agent.py | 4 ++-- griptape/structures/structure.py | 12 ++++++------ griptape/tasks/actions_subtask.py | 2 +- griptape/tasks/base_image_generation_task.py | 6 +++--- griptape/tasks/toolkit_task.py | 4 ++-- griptape/tools/base_tool.py | 10 +++++----- griptape/tools/computer/tool.py | 4 ++-- .../outpainting_image_generation_client/tool.py | 2 +- griptape/tools/rest_api_client/tool.py | 2 +- .../variation_image_generation_client/tool.py | 4 +++- griptape/utils/decorators.py | 7 ++++--- griptape/utils/deprecation.py | 2 +- griptape/utils/stream.py | 8 ++++---- pyproject.toml | 8 +++++++- 47 files changed, 129 insertions(+), 117 deletions(-) diff --git a/griptape/artifacts/list_artifact.py b/griptape/artifacts/list_artifact.py index 8590f57d3..298f29c6a 100644 --- a/griptape/artifacts/list_artifact.py +++ b/griptape/artifacts/list_artifact.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Optional -from attrs import define, field +from attrs import Attribute, define, field from griptape.artifacts import BaseArtifact @@ -17,7 +17,7 @@ class ListArtifact(BaseArtifact): validate_uniform_types: bool = field(default=False, kw_only=True, metadata={"serializable": True}) @value.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_value(self, _, value: list[BaseArtifact]) -> None: + def validate_value(self, _: Attribute, value: list[BaseArtifact]) -> None: if self.validate_uniform_types and len(value) > 0: first_type = type(value[0]) diff --git a/griptape/chunkers/base_chunker.py b/griptape/chunkers/base_chunker.py index 4383ce569..623185237 100644 --- a/griptape/chunkers/base_chunker.py +++ b/griptape/chunkers/base_chunker.py @@ -3,7 +3,7 @@ from abc import ABC from typing import Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.artifacts import TextArtifact from griptape.chunkers import ChunkSeparator @@ -28,7 +28,7 @@ class BaseChunker(ABC): ) @max_tokens.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_max_tokens(self, _, max_tokens: int) -> None: + def validate_max_tokens(self, _: Attribute, max_tokens: int) -> None: if max_tokens < 0: raise ValueError("max_tokens must be 0 or greater.") diff --git a/griptape/common/prompt_stack/messages/message.py b/griptape/common/prompt_stack/messages/message.py index 4bed14efb..64dec79c6 100644 --- a/griptape/common/prompt_stack/messages/message.py +++ b/griptape/common/prompt_stack/messages/message.py @@ -14,7 +14,7 @@ @define class Message(BaseMessage): - def __init__(self, content: str | list[BaseMessageContent], **kwargs: Any): + def __init__(self, content: str | list[BaseMessageContent], **kwargs: Any) -> None: if isinstance(content, str): content = [TextMessageContent(TextArtifact(value=content))] self.__attrs_init__(content, **kwargs) # pyright: ignore[reportAttributeAccessIssue] diff --git a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py index 1520afbcc..2e208d786 100644 --- a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py +++ b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py @@ -4,7 +4,7 @@ from urllib.parse import urljoin import requests -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.drivers.event_listener.base_event_listener_driver import BaseEventListenerDriver @@ -32,7 +32,7 @@ class GriptapeCloudEventListenerDriver(BaseEventListenerDriver): structure_run_id: str = field(default=Factory(lambda: os.getenv("GT_CLOUD_STRUCTURE_RUN_ID")), kw_only=True) @structure_run_id.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_run_id(self, _, structure_run_id: str): + def validate_run_id(self, _: Attribute, structure_run_id: str) -> None: if structure_run_id is None: raise ValueError( "structure_run_id must be set either in the constructor or as an environment variable (GT_CLOUD_STRUCTURE_RUN_ID).", diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index 18b591b41..4623f8231 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -4,7 +4,7 @@ from pathlib import Path from typing import TYPE_CHECKING, Any -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.utils.import_utils import import_optional_dependency @@ -32,7 +32,7 @@ class AmazonS3FileManagerDriver(BaseFileManagerDriver): s3_client: Any = field(default=Factory(lambda self: self.session.client("s3"), takes_self=True), kw_only=True) @workdir.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_workdir(self, _, workdir: str) -> None: + def validate_workdir(self, _: Attribute, workdir: str) -> None: if not Path(workdir).is_absolute(): raise ValueError("Workdir must be an absolute path") @@ -62,7 +62,7 @@ def try_load_file(self, path: str) -> bytes: else: raise e - def try_save_file(self, path: str, value: bytes): + def try_save_file(self, path: str, value: bytes) -> None: full_key = self._to_full_key(path) if self._is_a_directory(full_key): raise IsADirectoryError diff --git a/griptape/drivers/file_manager/base_file_manager_driver.py b/griptape/drivers/file_manager/base_file_manager_driver.py index db7f64438..1c4f1dd6a 100644 --- a/griptape/drivers/file_manager/base_file_manager_driver.py +++ b/griptape/drivers/file_manager/base_file_manager_driver.py @@ -97,4 +97,4 @@ def save_file(self, path: str, value: bytes | str) -> InfoArtifact | ErrorArtifa return ErrorArtifact(f"Failed to save file: {str(e)}") @abstractmethod - def try_save_file(self, path: str, value: bytes): ... + def try_save_file(self, path: str, value: bytes) -> None: ... diff --git a/griptape/drivers/file_manager/local_file_manager_driver.py b/griptape/drivers/file_manager/local_file_manager_driver.py index ad681e24b..4c2fcf5e6 100644 --- a/griptape/drivers/file_manager/local_file_manager_driver.py +++ b/griptape/drivers/file_manager/local_file_manager_driver.py @@ -3,7 +3,7 @@ import os from pathlib import Path -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from .base_file_manager_driver import BaseFileManagerDriver @@ -19,7 +19,7 @@ class LocalFileManagerDriver(BaseFileManagerDriver): workdir: str = field(default=Factory(lambda: os.getcwd()), kw_only=True) @workdir.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_workdir(self, _, workdir: str) -> None: + def validate_workdir(self, _: Attribute, workdir: str) -> None: if not Path(workdir).is_absolute(): raise ValueError("Workdir must be an absolute path") @@ -34,7 +34,7 @@ def try_load_file(self, path: str) -> bytes: with open(full_path, "rb") as file: return file.read() - def try_save_file(self, path: str, value: bytes): + def try_save_file(self, path: str, value: bytes) -> None: full_path = self._full_path(path) if self._is_dir(full_path): raise IsADirectoryError diff --git a/griptape/drivers/image_query/anthropic_image_query_driver.py b/griptape/drivers/image_query/anthropic_image_query_driver.py index c4756783e..4d91b6ea5 100644 --- a/griptape/drivers/image_query/anthropic_image_query_driver.py +++ b/griptape/drivers/image_query/anthropic_image_query_driver.py @@ -43,7 +43,7 @@ def try_query(self, query: str, images: list[ImageArtifact]) -> TextArtifact: return TextArtifact(text_content) - def _base_params(self, text_query: str, images: list[ImageArtifact]): + def _base_params(self, text_query: str, images: list[ImageArtifact]) -> dict: content = [self._construct_image_message(image) for image in images] content.append(self._construct_text_message(text_query)) messages = self._construct_messages(content) diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 70862f55f..440d6c3c5 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -3,7 +3,7 @@ import json from typing import TYPE_CHECKING, Any, Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.artifacts import TextArtifact from griptape.common import DeltaMessage, Message, PromptStack, TextMessageContent @@ -40,7 +40,7 @@ class AmazonSageMakerJumpstartPromptDriver(BasePromptDriver): ) @stream.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_stream(self, _, stream): + def validate_stream(self, _: Attribute, stream: bool) -> None: if stream: raise ValueError("streaming is not supported") diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index 57cb7272d..f2a5522d6 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -143,7 +143,9 @@ def __process_stream(self, prompt_stack: PromptStack) -> Message: return result - def __build_message(self, delta_contents: list[list[BaseDeltaMessageContent]], usage: DeltaMessage.Usage): + def __build_message( + self, delta_contents: list[list[BaseDeltaMessageContent]], usage: DeltaMessage.Usage + ) -> Message: content = [] for delta_content in delta_contents: text_deltas = [delta for delta in delta_content if isinstance(delta, TextDeltaMessageContent)] diff --git a/griptape/drivers/sql/amazon_redshift_sql_driver.py b/griptape/drivers/sql/amazon_redshift_sql_driver.py index fc97d4e7e..5ae85c495 100644 --- a/griptape/drivers/sql/amazon_redshift_sql_driver.py +++ b/griptape/drivers/sql/amazon_redshift_sql_driver.py @@ -3,7 +3,7 @@ import time from typing import TYPE_CHECKING, Any, Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.drivers import BaseSqlDriver @@ -26,14 +26,14 @@ class AmazonRedshiftSqlDriver(BaseSqlDriver): ) @workgroup_name.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_params(self, _, workgroup_name: Optional[str]) -> None: + def validate_params(self, _: Attribute, workgroup_name: Optional[str]) -> None: if not self.cluster_identifier and not self.workgroup_name: raise ValueError("Provide a value for one of `cluster_identifier` or `workgroup_name`") elif self.cluster_identifier and self.workgroup_name: raise ValueError("Provide a value for either `cluster_identifier` or `workgroup_name`, but not both") @classmethod - def _process_rows_from_records(cls, records) -> list[list]: + def _process_rows_from_records(cls, records: list) -> list[list]: return [[c[list(c.keys())[0]] for c in r] for r in records] @classmethod @@ -41,11 +41,11 @@ def _process_cells_from_rows_and_columns(cls, columns: list, rows: list[list]) - return [{column: r[idx] for idx, column in enumerate(columns)} for r in rows] @classmethod - def _process_columns_from_column_metadata(cls, meta) -> list: + def _process_columns_from_column_metadata(cls, meta: dict) -> list: return [k["name"] for k in meta] @classmethod - def _post_process(cls, meta, records) -> list[dict[str, Any]]: + def _post_process(cls, meta: dict, records: list) -> list[dict[str, Any]]: columns = cls._process_columns_from_column_metadata(meta) rows = cls._process_rows_from_records(records) return cls._process_cells_from_rows_and_columns(columns, rows) diff --git a/griptape/drivers/sql/snowflake_sql_driver.py b/griptape/drivers/sql/snowflake_sql_driver.py index 6fa75bb1c..43d147663 100644 --- a/griptape/drivers/sql/snowflake_sql_driver.py +++ b/griptape/drivers/sql/snowflake_sql_driver.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Any, Callable, Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.drivers import BaseSqlDriver from griptape.utils import import_optional_dependency @@ -29,7 +29,7 @@ class SnowflakeSqlDriver(BaseSqlDriver): ) @connection_func.validator # pyright: ignore[reportFunctionMemberAccess] - def validate_connection_func(self, _, connection_func: Callable[[], SnowflakeConnection]) -> None: + def validate_connection_func(self, _: Attribute, connection_func: Callable[[], SnowflakeConnection]) -> None: snowflake_connection = connection_func() snowflake = import_optional_dependency("snowflake") @@ -39,7 +39,7 @@ def validate_connection_func(self, _, connection_func: Callable[[], SnowflakeCon raise ValueError("Provide a schema and database for the Snowflake connection") @engine.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_engine_url(self, _, engine: Engine) -> None: + def validate_engine_url(self, _: Attribute, engine: Engine) -> None: if not engine.url.render_as_string().startswith("snowflake://"): raise ValueError("Provide a Snowflake connection") diff --git a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py index 4929c58f2..f85f5b9ea 100644 --- a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any, NoReturn, Optional from urllib.parse import urljoin import requests @@ -107,5 +107,5 @@ def query( entry_list = [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] return entry_list - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") diff --git a/griptape/drivers/vector/local_vector_store_driver.py b/griptape/drivers/vector/local_vector_store_driver.py index f9520c0be..68fa4561b 100644 --- a/griptape/drivers/vector/local_vector_store_driver.py +++ b/griptape/drivers/vector/local_vector_store_driver.py @@ -4,7 +4,7 @@ import os import threading from dataclasses import asdict -from typing import Callable, Optional, TextIO +from typing import Callable, NoReturn, Optional, TextIO from attrs import Factory, define, field from numpy import dot @@ -114,8 +114,8 @@ def query( for r in result ] - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") - def _namespaced_vector_id(self, vector_id: str, namespace: Optional[str]): + def _namespaced_vector_id(self, vector_id: str, namespace: Optional[str]) -> str: return vector_id if namespace is None else f"{namespace}-{vector_id}" diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index 0c8940238..38c6f7977 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any, NoReturn, Optional from attrs import Factory, define, field @@ -250,5 +250,5 @@ def upsert_vector( """ raise NotImplementedError(f"{self.__class__.__name__} does not support upserting a vector.") - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") diff --git a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py index 3a96a9741..26d92e6fd 100644 --- a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py +++ b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py @@ -171,7 +171,7 @@ def query( return results - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> None: """Deletes the vector from the collection.""" collection = self.get_collection() collection.delete_one({"_id": vector_id}) diff --git a/griptape/drivers/vector/opensearch_vector_store_driver.py b/griptape/drivers/vector/opensearch_vector_store_driver.py index 31921a0df..7f4044e19 100644 --- a/griptape/drivers/vector/opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/opensearch_vector_store_driver.py @@ -1,7 +1,7 @@ from __future__ import annotations import logging -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, NoReturn, Optional from attrs import Factory, define, field @@ -125,7 +125,7 @@ def query( count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, - include_metadata=True, + include_metadata: bool = True, field_name: str = "vector", **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: @@ -164,5 +164,5 @@ def query( for hit in response["hits"]["hits"] ] - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index ffc7a7516..2d3d5bf65 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -3,9 +3,9 @@ import uuid from collections import OrderedDict from dataclasses import dataclass -from typing import Any, Optional, cast +from typing import Any, NoReturn, Optional, cast -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from sqlalchemy import JSON, Column, String, create_engine from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.engine import Engine @@ -34,7 +34,7 @@ class PgVectorVectorStoreDriver(BaseVectorStoreDriver): _model: Any = field(default=Factory(lambda self: self.default_vector_model(), takes_self=True)) @connection_string.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_connection_string(self, _, connection_string: Optional[str]) -> None: + def validate_connection_string(self, _: Attribute, connection_string: Optional[str]) -> None: # If an engine is provided, the connection string is not used. if self.engine is not None: return @@ -47,7 +47,7 @@ def validate_connection_string(self, _, connection_string: Optional[str]) -> Non raise ValueError("The connection string must describe a Postgres database connection") @engine.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_engine(self, _, engine: Optional[Engine]) -> None: + def validate_engine(self, _: Attribute, engine: Optional[Engine]) -> None: # If a connection string is provided, an engine does not need to be provided. if self.connection_string is not None: return @@ -191,5 +191,5 @@ class VectorModel(Base): return VectorModel - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") diff --git a/griptape/drivers/vector/pinecone_vector_store_driver.py b/griptape/drivers/vector/pinecone_vector_store_driver.py index 240829b7c..94754317d 100644 --- a/griptape/drivers/vector/pinecone_vector_store_driver.py +++ b/griptape/drivers/vector/pinecone_vector_store_driver.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any, NoReturn, Optional from attrs import define, field @@ -89,7 +89,7 @@ def query( namespace: Optional[str] = None, include_vectors: bool = False, # PineconeVectorStorageDriver-specific params: - include_metadata=True, + include_metadata: bool = True, **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: vector = self.embedding_driver.embed_string(query) @@ -114,5 +114,5 @@ def query( for r in results["matches"] ] - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index aec02e59a..a676dd908 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -1,7 +1,7 @@ from __future__ import annotations import json -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING, NoReturn, Optional import numpy as np from attrs import Factory, define, field @@ -165,5 +165,5 @@ def _get_doc_prefix(self, namespace: Optional[str] = None) -> str: """Get the document prefix based on the provided namespace.""" return f"{namespace}:" if namespace else "" - def delete_vector(self, vector_id: str): + def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") diff --git a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py index d285d773e..6e25ca3b6 100644 --- a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py @@ -1,7 +1,7 @@ from __future__ import annotations import re -from typing import Optional +from typing import Any, Optional from attrs import Factory, define, field @@ -48,7 +48,7 @@ def scrape_url(self, url: str) -> TextArtifact: # Custom MarkdownConverter to optionally linked urls. If include_links is False only # the text of the link is returned. class OptionalLinksMarkdownConverter(MarkdownConverter): - def convert_a(self, el, text, convert_as_inline): + def convert_a(self, el: Any, text: str, convert_as_inline: Any) -> str: if include_links: return super().convert_a(el, text, convert_as_inline) return text @@ -56,7 +56,7 @@ def convert_a(self, el, text, convert_as_inline): with sync_playwright() as p, p.chromium.launch(headless=True) as browser: page = browser.new_page() - def skip_loading_images(route): + def skip_loading_images(route: Any) -> Any: if route.request.resource_type == "image": return route.abort() route.continue_() diff --git a/griptape/engines/extraction/base_extraction_engine.py b/griptape/engines/extraction/base_extraction_engine.py index f0a658fe7..f263ee0aa 100644 --- a/griptape/engines/extraction/base_extraction_engine.py +++ b/griptape/engines/extraction/base_extraction_engine.py @@ -3,7 +3,7 @@ from abc import ABC, abstractmethod from typing import TYPE_CHECKING, Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.chunkers import BaseChunker, TextChunker @@ -27,7 +27,7 @@ class BaseExtractionEngine(ABC): ) @max_token_multiplier.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_max_token_multiplier(self, _, max_token_multiplier: int) -> None: + def validate_max_token_multiplier(self, _: Attribute, max_token_multiplier: int) -> None: if max_token_multiplier > 1: raise ValueError("has to be less than or equal to 1") elif max_token_multiplier <= 0: diff --git a/griptape/engines/summary/prompt_summary_engine.py b/griptape/engines/summary/prompt_summary_engine.py index 3cf0d6f3e..c5d8e695d 100644 --- a/griptape/engines/summary/prompt_summary_engine.py +++ b/griptape/engines/summary/prompt_summary_engine.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Optional, cast -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.artifacts import ListArtifact, TextArtifact from griptape.chunkers import BaseChunker, TextChunker @@ -32,7 +32,7 @@ class PromptSummaryEngine(BaseSummaryEngine): ) @max_token_multiplier.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_allowlist(self, _, max_token_multiplier: int) -> None: + def validate_allowlist(self, _: Attribute, max_token_multiplier: int) -> None: if max_token_multiplier > 1: raise ValueError("has to be less than or equal to 1") elif max_token_multiplier <= 0: diff --git a/griptape/exceptions/dummy_exception.py b/griptape/exceptions/dummy_exception.py index 0e17898bd..3b4de955a 100644 --- a/griptape/exceptions/dummy_exception.py +++ b/griptape/exceptions/dummy_exception.py @@ -1,5 +1,5 @@ class DummyException(Exception): - def __init__(self, dummy_class_name: str, dummy_method_name: str): + def __init__(self, dummy_class_name: str, dummy_method_name: str) -> None: message = ( f"You have attempted to use a {dummy_class_name}'s {dummy_method_name} method. " "This likely originated from using a `StructureConfig` without providing a Driver required for this feature." diff --git a/griptape/loaders/email_loader.py b/griptape/loaders/email_loader.py index e13558ab3..a54d5a063 100644 --- a/griptape/loaders/email_loader.py +++ b/griptape/loaders/email_loader.py @@ -75,7 +75,7 @@ def load(self, source: EmailQuery, *args, **kwargs) -> ListArtifact | ErrorArtif logging.error(e) return ErrorArtifact(f"error retrieving email: {e}") - def _count_messages(self, message_numbers: bytes): + def _count_messages(self, message_numbers: bytes) -> int: return len(list(filter(None, message_numbers.decode().split(" ")))) def load_collection(self, sources: list[EmailQuery], *args, **kwargs) -> dict[str, ListArtifact | ErrorArtifact]: diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index d68d03209..4fdb4011c 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Any, Optional -from attrs import define, field +from attrs import Attribute, define, field from griptape.artifacts import BaseArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.engines.rag import RagContext, RagEngine @@ -23,7 +23,7 @@ class TextArtifactStorage(BaseArtifactStorage): json_extraction_engine: Optional[JsonExtractionEngine] = field(default=None) @rag_engine.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_rag_engine(self, _, rag_engine: str) -> None: + def validate_rag_engine(self, _: Attribute, rag_engine: str) -> None: if rag_engine is not None and self.retrieval_rag_module_name is None: raise ValueError("You have to set retrieval_rag_module_name if rag_engine is provided") diff --git a/griptape/memory/task/task_memory.py b/griptape/memory/task/task_memory.py index 79c375cdb..e2131d1f0 100644 --- a/griptape/memory/task/task_memory.py +++ b/griptape/memory/task/task_memory.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Any, Callable, Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.memory.meta import ActionSubtaskMetaEntry @@ -21,7 +21,7 @@ class TaskMemory(ActivityMixin): namespace_metadata: dict[str, Any] = field(factory=dict, kw_only=True) @artifact_storages.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_artifact_storages(self, _, artifact_storage: dict[type, BaseArtifactStorage]) -> None: + def validate_artifact_storages(self, _: Attribute, artifact_storage: dict[type, BaseArtifactStorage]) -> None: seen_types = [] for storage in artifact_storage.values(): @@ -31,7 +31,7 @@ def validate_artifact_storages(self, _, artifact_storage: dict[type, BaseArtifac seen_types.append(type(storage)) def get_storage_for(self, artifact: BaseArtifact) -> Optional[BaseArtifactStorage]: - def find_storage(a): + def find_storage(a: BaseArtifact) -> Optional[BaseArtifactStorage]: return next((v for k, v in self.artifact_storages.items() if isinstance(a, k)), None) if isinstance(artifact, ListArtifact): diff --git a/griptape/mixins/activity_mixin.py b/griptape/mixins/activity_mixin.py index 0178e342f..2caee49e4 100644 --- a/griptape/mixins/activity_mixin.py +++ b/griptape/mixins/activity_mixin.py @@ -4,7 +4,7 @@ from typing import Callable, Optional import schema -from attrs import define, field +from attrs import Attribute, define, field from jinja2 import Template from schema import Literal, Schema @@ -15,7 +15,7 @@ class ActivityMixin: denylist: Optional[list[str]] = field(default=None, kw_only=True) @allowlist.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_allowlist(self, _, allowlist: Optional[list[str]]) -> None: + def validate_allowlist(self, _: Attribute, allowlist: Optional[list[str]]) -> None: if allowlist is None: return @@ -26,7 +26,7 @@ def validate_allowlist(self, _, allowlist: Optional[list[str]]) -> None: self._validate_tool_activity(activity_name) @denylist.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_denylist(self, _, denylist: Optional[list[str]]) -> None: + def validate_denylist(self, _: Attribute, denylist: Optional[list[str]]) -> None: if denylist is None: return @@ -95,7 +95,7 @@ def activity_to_input(self, activity: Callable) -> dict: else: return {schema.Optional("input"): {}} - def _validate_tool_activity(self, activity_name): + def _validate_tool_activity(self, activity_name: str) -> None: tool = self.__class__ activity = getattr(tool, activity_name, None) diff --git a/griptape/mixins/media_artifact_file_output_mixin.py b/griptape/mixins/media_artifact_file_output_mixin.py index 36907634b..4097960bd 100644 --- a/griptape/mixins/media_artifact_file_output_mixin.py +++ b/griptape/mixins/media_artifact_file_output_mixin.py @@ -3,7 +3,7 @@ import os from typing import TYPE_CHECKING, Optional -from attrs import define, field +from attrs import Attribute, define, field if TYPE_CHECKING: from griptape.artifacts import BlobArtifact @@ -15,7 +15,7 @@ class BlobArtifactFileOutputMixin: output_file: Optional[str] = field(default=None, kw_only=True) @output_dir.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_output_dir(self, _, output_dir: str) -> None: + def validate_output_dir(self, _: Attribute, output_dir: str) -> None: if not output_dir: return @@ -23,7 +23,7 @@ def validate_output_dir(self, _, output_dir: str) -> None: raise ValueError("Can't have both output_dir and output_file specified.") @output_file.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_output_file(self, _, output_file: str) -> None: + def validate_output_file(self, _: Attribute, output_file: str) -> None: if not output_file: return diff --git a/griptape/mixins/rule_mixin.py b/griptape/mixins/rule_mixin.py index 920c17c5b..ff4395270 100644 --- a/griptape/mixins/rule_mixin.py +++ b/griptape/mixins/rule_mixin.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Optional -from attrs import define, field +from attrs import Attribute, define, field from griptape.rules import Rule, Ruleset @@ -20,7 +20,7 @@ class RuleMixin: structure: Optional[Structure] = field(default=None, kw_only=True) @rulesets.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: + def validate_rulesets(self, _: Attribute, rulesets: list[Ruleset]) -> None: if not rulesets: return @@ -28,7 +28,7 @@ def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: raise ValueError("Can't have both rulesets and rules specified.") @rules.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_rules(self, _, rules: list[Rule]) -> None: + def validate_rules(self, _: Attribute, rules: list[Rule]) -> None: if not rules: return diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 982c155e4..0bf7c4760 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -2,7 +2,7 @@ from abc import ABC from collections.abc import Sequence -from typing import Literal, Union, get_args, get_origin +from typing import Any, Literal, Union, get_args, get_origin import attrs from marshmallow import INCLUDE, Schema, fields @@ -29,7 +29,7 @@ def from_attrs_cls(cls, attrs_cls: type) -> type: class SubSchema(cls): @post_load - def make_obj(self, data, **kwargs): + def make_obj(self, data: Any, **kwargs) -> Any: return attrs_cls(**data) if issubclass(attrs_cls, SerializableMixin): diff --git a/griptape/schemas/bytes_field.py b/griptape/schemas/bytes_field.py index ac2830388..fb08b65a3 100644 --- a/griptape/schemas/bytes_field.py +++ b/griptape/schemas/bytes_field.py @@ -1,15 +1,16 @@ import base64 +from typing import Any from marshmallow import ValidationError, fields class Bytes(fields.Field): - def _serialize(self, value, attr, obj, **kwargs): + def _serialize(self, value: Any, attr: Any, obj: Any, **kwargs) -> str: return base64.b64encode(value).decode() - def _deserialize(self, value, attr, data, **kwargs): + def _deserialize(self, value: Any, attr: Any, data: Any, **kwargs) -> bytes: return base64.b64decode(value) - def _validate(self, value): + def _validate(self, value: Any) -> None: if not isinstance(value, bytes): raise ValidationError("Invalid input type.") diff --git a/griptape/schemas/polymorphic_schema.py b/griptape/schemas/polymorphic_schema.py index 87772539c..f31f7a922 100644 --- a/griptape/schemas/polymorphic_schema.py +++ b/griptape/schemas/polymorphic_schema.py @@ -8,7 +8,7 @@ class PolymorphicSchema(BaseSchema): """PolymorphicSchema is based on https://github.com/marshmallow-code/marshmallow-oneofschema.""" - def __init__(self, inner_class: Any, **kwargs): + def __init__(self, inner_class: Any, **kwargs) -> None: super().__init__(**kwargs) self.inner_class = inner_class @@ -16,18 +16,18 @@ def __init__(self, inner_class: Any, **kwargs): type_field = "type" type_field_remove = True - def get_obj_type(self, obj): + def get_obj_type(self, obj: Any) -> Any: """Returns name of the schema during dump() calls, given the object being dumped.""" return obj.__class__.__name__ - def get_data_type(self, data): + def get_data_type(self, data: Any) -> Any: """Returns name of the schema during load() calls, given the data being loaded. Defaults to looking up `type_field` in the data.""" data_type = data.get(self.type_field) if self.type_field in data and self.type_field_remove: data.pop(self.type_field) return data_type - def dump(self, obj, *, many=None, **kwargs): + def dump(self, obj: Any, *, many: Any = None, **kwargs) -> Any: errors = {} result_data = [] result_errors = {} @@ -52,7 +52,7 @@ def dump(self, obj, *, many=None, **kwargs): exc = ValidationError(errors, data=obj, valid_data=result) # pyright: ignore[reportArgumentType] raise exc - def _dump(self, obj, *, update_fields=True, **kwargs): + def _dump(self, obj: Any, *, update_fields: bool = True, **kwargs) -> Any: obj_type = self.get_obj_type(obj) if not obj_type: @@ -74,7 +74,7 @@ def _dump(self, obj, *, update_fields=True, **kwargs): return result - def load(self, data, *, many=None, partial=None, unknown=None, **kwargs): + def load(self, data: Any, *, many: Any = None, partial: Any = None, unknown: Any = None, **kwargs) -> Any: errors = {} result_data = [] result_errors = {} @@ -106,7 +106,7 @@ def load(self, data, *, many=None, partial=None, unknown=None, **kwargs): exc = ValidationError(errors, data=data, valid_data=result) raise exc - def _load(self, data, *, partial=None, unknown=None, **kwargs): + def _load(self, data: Any, *, partial: Any = None, unknown: Any = None, **kwargs) -> Any: if not isinstance(data, dict): raise ValidationError({"_schema": f"Invalid data type: {data}"}) @@ -127,7 +127,7 @@ def _load(self, data, *, partial=None, unknown=None, **kwargs): return schema.load(data, many=False, partial=partial, unknown=unknown, **kwargs) - def validate(self, data, *, many=None, partial=None): # pyright: ignore[reportIncompatibleMethodOverride] + def validate(self, data: Any, *, many: Any = None, partial: Any = None) -> Any: # pyright: ignore[reportIncompatibleMethodOverride] try: self.load(data, many=many, partial=partial) except ValidationError as ve: diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 4aedd98ad..569accffc 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -2,7 +2,7 @@ from typing import TYPE_CHECKING, Callable, Optional -from attrs import define, field +from attrs import Attribute, define, field from griptape.artifacts.text_artifact import TextArtifact from griptape.memory.structure import Run @@ -25,7 +25,7 @@ class Agent(Structure): fail_fast: bool = field(default=False, kw_only=True) @fail_fast.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_fail_fast(self, _, fail_fast: bool) -> None: + def validate_fail_fast(self, _: Attribute, fail_fast: bool) -> None: if fail_fast: raise ValueError("Agents cannot fail fast, as they can only have 1 task.") diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 5e2615c9d..5a37c137e 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -6,7 +6,7 @@ from logging import Logger from typing import TYPE_CHECKING, Any, Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from rich.logging import RichHandler from griptape.artifacts import BaseArtifact, BlobArtifact, TextArtifact @@ -73,7 +73,7 @@ class Structure(ABC): _logger: Optional[Logger] = None @rulesets.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: + def validate_rulesets(self, _: Attribute, rulesets: list[Ruleset]) -> None: if not rulesets: return @@ -81,7 +81,7 @@ def validate_rulesets(self, _, rulesets: list[Ruleset]) -> None: raise ValueError("can't have both rulesets and rules specified") @rules.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_rules(self, _, rules: list[Rule]) -> None: + def validate_rules(self, _: Attribute, rules: list[Rule]) -> None: if not rules: return @@ -100,17 +100,17 @@ def __add__(self, other: BaseTask | list[BaseTask]) -> list[BaseTask]: return self.add_tasks(*other) if isinstance(other, list) else self + [other] @prompt_driver.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_prompt_driver(self, attribute, value): + def validate_prompt_driver(self, attribute: Attribute, value: BasePromptDriver) -> None: if value is not None: deprecation_warn(f"`{attribute.name}` is deprecated, use `config.prompt_driver` instead.") @embedding_driver.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_embedding_driver(self, attribute, value): + def validate_embedding_driver(self, attribute: Attribute, value: BaseEmbeddingDriver) -> None: if value is not None: deprecation_warn(f"`{attribute.name}` is deprecated, use `config.embedding_driver` instead.") @stream.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_stream(self, attribute, value): + def validate_stream(self, attribute: Attribute, value: bool) -> None: if value is not None: deprecation_warn(f"`{attribute.name}` is deprecated, use `config.prompt_driver.stream` instead.") diff --git a/griptape/tasks/actions_subtask.py b/griptape/tasks/actions_subtask.py index 66ec9c0b0..0a00fba42 100644 --- a/griptape/tasks/actions_subtask.py +++ b/griptape/tasks/actions_subtask.py @@ -64,7 +64,7 @@ def children(self) -> list[BaseTask]: else: raise Exception("ActionSubtask must be attached to a Task that implements ActionSubtaskOriginMixin.") - def attach_to(self, parent_task: BaseTask): + def attach_to(self, parent_task: BaseTask) -> None: self.parent_task_id = parent_task.id self.structure = parent_task.structure diff --git a/griptape/tasks/base_image_generation_task.py b/griptape/tasks/base_image_generation_task.py index a6e8ad8ef..2f5d46475 100644 --- a/griptape/tasks/base_image_generation_task.py +++ b/griptape/tasks/base_image_generation_task.py @@ -4,7 +4,7 @@ from abc import ABC from typing import TYPE_CHECKING -from attrs import define, field +from attrs import Attribute, define, field from griptape.loaders import ImageLoader from griptape.mixins import BlobArtifactFileOutputMixin, RuleMixin @@ -32,7 +32,7 @@ class BaseImageGenerationTask(BlobArtifactFileOutputMixin, RuleMixin, BaseTask, negative_rules: list[Rule] = field(factory=list, kw_only=True) @negative_rulesets.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_negative_rulesets(self, _, negative_rulesets: list[Ruleset]) -> None: + def validate_negative_rulesets(self, _: Attribute, negative_rulesets: list[Ruleset]) -> None: if not negative_rulesets: return @@ -40,7 +40,7 @@ def validate_negative_rulesets(self, _, negative_rulesets: list[Ruleset]) -> Non raise ValueError("Can't have both negative_rulesets and negative_rules specified.") @negative_rules.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_negative_rules(self, _, negative_rules: list[Rule]) -> None: + def validate_negative_rules(self, _: Attribute, negative_rules: list[Rule]) -> None: if not negative_rules: return diff --git a/griptape/tasks/toolkit_task.py b/griptape/tasks/toolkit_task.py index 8f3519c32..59d8f9f90 100644 --- a/griptape/tasks/toolkit_task.py +++ b/griptape/tasks/toolkit_task.py @@ -3,7 +3,7 @@ import json from typing import TYPE_CHECKING, Callable, Optional -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape import utils from griptape.artifacts import ActionArtifact, BaseArtifact, ErrorArtifact, ListArtifact, TextArtifact @@ -46,7 +46,7 @@ def __attrs_post_init__(self) -> None: self.set_default_tools_memory(self.task_memory) @tools.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_tools(self, _, tools: list[BaseTool]) -> None: + def validate_tools(self, _: Attribute, tools: list[BaseTool]) -> None: tool_names = [t.name for t in tools] if len(tool_names) > len(set(tool_names)): diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index eb1689c86..60eb10cda 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -9,7 +9,7 @@ from typing import TYPE_CHECKING, Callable, Optional import yaml -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from schema import Literal, Or, Schema from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, TextArtifact @@ -51,7 +51,7 @@ def __attrs_post_init__(self) -> None: self.install_dependencies(os.environ.copy()) @output_memory.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_output_memory(self, _, output_memory: dict[str, Optional[list[TaskMemory]]]) -> None: + def validate_output_memory(self, _: Attribute, output_memory: dict[str, Optional[list[TaskMemory]]]) -> None: if output_memory: for activity_name, memory_list in output_memory.items(): if not self.find_activity(activity_name): @@ -78,11 +78,11 @@ def manifest(self) -> dict: return yaml.safe_load(yaml_file) @property - def abs_file_path(self): + def abs_file_path(self) -> str: return os.path.abspath(inspect.getfile(self.__class__)) @property - def abs_dir_path(self): + def abs_dir_path(self) -> str: return os.path.dirname(self.abs_file_path) # This method has to remain a method and can't be decorated with @property because @@ -174,7 +174,7 @@ def validate(self) -> bool: return True - def tool_dir(self): + def tool_dir(self) -> str: class_file = inspect.getfile(self.__class__) return os.path.dirname(os.path.abspath(class_file)) diff --git a/griptape/tools/computer/tool.py b/griptape/tools/computer/tool.py index 08a1f6976..4416cf5fa 100644 --- a/griptape/tools/computer/tool.py +++ b/griptape/tools/computer/tool.py @@ -9,7 +9,7 @@ import docker import stringcase -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from docker.errors import NotFound from docker.models.containers import Container from schema import Literal, Schema @@ -52,7 +52,7 @@ def __attrs_post_init__(self) -> None: self.local_workdir = self._tempdir.name @docker_client.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_docker_client(self, _, docker_client: DockerClient) -> None: + def validate_docker_client(self, _: Attribute, docker_client: DockerClient) -> None: if not docker_client: raise ValueError("Docker client can't be initialized: make sure the Docker daemon is running") diff --git a/griptape/tools/outpainting_image_generation_client/tool.py b/griptape/tools/outpainting_image_generation_client/tool.py index e11bb8cd8..22f47b866 100644 --- a/griptape/tools/outpainting_image_generation_client/tool.py +++ b/griptape/tools/outpainting_image_generation_client/tool.py @@ -123,7 +123,7 @@ def _generate_outpainting( negative_prompts: list[str], image_artifact: ImageArtifact, mask_artifact: ImageArtifact, - ): + ) -> ImageArtifact: output_artifact = self.engine.run( prompts=prompts, negative_prompts=negative_prompts, diff --git a/griptape/tools/rest_api_client/tool.py b/griptape/tools/rest_api_client/tool.py index 6d359e20e..b27beda0e 100644 --- a/griptape/tools/rest_api_client/tool.py +++ b/griptape/tools/rest_api_client/tool.py @@ -209,7 +209,7 @@ def delete(self, params: dict) -> BaseArtifact: except exceptions.RequestException as err: return ErrorArtifact(str(err)) - def _build_url(self, base_url, path=None, path_params=None): + def _build_url(self, base_url: str, path: Optional[str] = None, path_params: Optional[list] = None) -> str: url = "" if path: diff --git a/griptape/tools/variation_image_generation_client/tool.py b/griptape/tools/variation_image_generation_client/tool.py index e82561c59..deab543a1 100644 --- a/griptape/tools/variation_image_generation_client/tool.py +++ b/griptape/tools/variation_image_generation_client/tool.py @@ -98,7 +98,9 @@ def image_variation_from_memory(self, params: dict[str, Any]) -> ImageArtifact | return self._generate_variation(prompts, negative_prompts, cast(ImageArtifact, image_artifact)) - def _generate_variation(self, prompts: list[str], negative_prompts: list[str], image_artifact: ImageArtifact): + def _generate_variation( + self, prompts: list[str], negative_prompts: list[str], image_artifact: ImageArtifact + ) -> ImageArtifact: output_artifact = self.engine.run(prompts=prompts, negative_prompts=negative_prompts, image=image_artifact) if self.output_dir or self.output_file: diff --git a/griptape/utils/decorators.py b/griptape/utils/decorators.py index 83811d9a6..10bf6c9a4 100644 --- a/griptape/utils/decorators.py +++ b/griptape/utils/decorators.py @@ -1,4 +1,5 @@ import functools +from typing import Any, Callable import schema from schema import Schema @@ -6,7 +7,7 @@ CONFIG_SCHEMA = Schema({"description": str, schema.Optional("schema"): Schema}) -def activity(config: dict): +def activity(config: dict) -> Any: validated_config = CONFIG_SCHEMA.validate(config) validated_config.update({k: v for k, v in config.items() if k not in validated_config}) @@ -14,9 +15,9 @@ def activity(config: dict): if not validated_config.get("schema"): validated_config["schema"] = None - def decorator(func): + def decorator(func: Callable) -> Any: @functools.wraps(func) - def wrapper(self, *args, **kwargs): + def wrapper(self: Any, *args, **kwargs) -> Any: return func(self, *args, **kwargs) setattr(wrapper, "name", func.__name__) diff --git a/griptape/utils/deprecation.py b/griptape/utils/deprecation.py index f52ea7c64..0b69f1b4f 100644 --- a/griptape/utils/deprecation.py +++ b/griptape/utils/deprecation.py @@ -1,7 +1,7 @@ import warnings -def deprecation_warn(message: str, stacklevel: int = 2): +def deprecation_warn(message: str, stacklevel: int = 2) -> None: warnings.simplefilter("always", DeprecationWarning) warnings.warn(message, category=DeprecationWarning, stacklevel=stacklevel) warnings.simplefilter("default", DeprecationWarning) diff --git a/griptape/utils/stream.py b/griptape/utils/stream.py index fe0cf50d7..372004423 100644 --- a/griptape/utils/stream.py +++ b/griptape/utils/stream.py @@ -4,7 +4,7 @@ from threading import Thread from typing import TYPE_CHECKING -from attrs import Factory, define, field +from attrs import Attribute, Factory, define, field from griptape.artifacts.text_artifact import TextArtifact from griptape.events.completion_chunk_event import CompletionChunkEvent @@ -36,7 +36,7 @@ class Stream: structure: Structure = field() @structure.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_structure(self, _, structure: Structure): + def validate_structure(self, _: Attribute, structure: Structure) -> None: if structure and not structure.config.prompt_driver.stream: raise ValueError("prompt driver does not have streaming enabled, enable with stream=True") @@ -56,8 +56,8 @@ def run(self, *args) -> Iterator[TextArtifact]: yield TextArtifact(value=event.token) t.join() - def _run_structure(self, *args): - def event_handler(event: BaseEvent): + def _run_structure(self, *args) -> None: + def event_handler(event: BaseEvent) -> None: self._event_queue.put(event) stream_event_listener = EventListener( diff --git a/pyproject.toml b/pyproject.toml index 0c0d28d3f..2e094141a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -215,6 +215,7 @@ select = [ "FA", # flake8-future-annotations "COM", # flake8-commas "C4", # flake8-comprehensions + "ANN", # flake8-annotations ] ignore = [ "UP007", # non-pep604-annotation @@ -230,7 +231,12 @@ ignore = [ "D105", # undocumented-magic-method "D106", # undocumented-public-nested-class "D107", # undocumented-public-init - "COM812" # missing-trailing-comma -- See https://github.com/astral-sh/ruff/issues/9216 + "COM812", # missing-trailing-comma -- See https://github.com/astral-sh/ruff/issues/9216 + "ANN002", # missing-type-args + "ANN003", # missing-type-kwargs + "ANN101", # missing-type-self + "ANN102", # missing-type-cls + "ANN401", # any-type ] [tool.ruff.lint.pydocstyle] convention = "google" From b99a828482877eb68284ab3c3e1efb2d9364abf1 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 16 Jul 2024 07:24:23 -0700 Subject: [PATCH 73/87] Add flake8-boolean-trap ruff rule (#985) --- CHANGELOG.md | 9 ++++++ griptape/artifacts/boolean_artifact.py | 4 +-- .../base_event_listener_driver.py | 6 ++-- ...mazon_sagemaker_jumpstart_prompt_driver.py | 2 +- .../amazon_opensearch_vector_store_driver.py | 1 + .../azure_mongodb_vector_store_driver.py | 1 + .../vector/base_vector_store_driver.py | 30 ++++++++++++------- .../vector/dummy_vector_store_driver.py | 5 ++-- ...loud_knowledge_base_vector_store_driver.py | 7 +++-- .../vector/local_vector_store_driver.py | 12 ++++---- .../vector/marqo_vector_store_driver.py | 8 +++-- .../mongodb_atlas_vector_store_driver.py | 6 ++-- .../vector/opensearch_vector_store_driver.py | 6 ++-- .../vector/pgvector_vector_store_driver.py | 7 +++-- .../vector/pinecone_vector_store_driver.py | 6 ++-- .../vector/qdrant_vector_store_driver.py | 6 ++-- .../vector/redis_vector_store_driver.py | 7 +++-- griptape/events/event_listener.py | 2 +- .../task/storage/text_artifact_storage.py | 4 +-- griptape/structures/agent.py | 2 +- griptape/structures/structure.py | 6 ++-- griptape/structures/workflow.py | 4 ++- griptape/utils/dict_utils.py | 2 +- pyproject.toml | 1 + .../test_base_local_vector_store_driver.py | 12 ++++---- .../vector/test_dummy_vector_store_driver.py | 2 +- .../vector/test_local_vector_store_driver.py | 6 ++-- .../vector/test_qdrant_vector_store_driver.py | 2 +- 28 files changed, 104 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8d6002e1..151a2199a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. ### Changed +- **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifacts` optional arguments are now keyword-only arguments. +- **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifact` optional arguments are now keyword-only arguments. +- **BREAKING**: `BaseVectorStoreDriver.upsert_text` optional arguments are now keyword-only arguments. +- **BREAKING**: `BaseVectorStoreDriver.does_entry_exist` optional arguments are now keyword-only arguments. +- **BREAKING**: `BaseVectorStoreDriver.load_artifacts` optional arguments are now keyword-only arguments. +- **BREAKING**: `BaseVectorStoreDriver.upsert_vector` optional arguments are now keyword-only arguments. +- **BREAKING**: `BaseVectorStoreDriver.query` optional arguments are now keyword-only arguments. +- **BREAKING**: `EventListener.publish_event`'s `flush` argument is now a keyword-only argument. +- **BREAKING**: `BaseEventListenerDriver.publish_event`'s `flush` argument is now a keyword-only argument. ### Fixed - Parameter `count` for `QdrantVectorStoreDriver.query` now optional as per documentation. diff --git a/griptape/artifacts/boolean_artifact.py b/griptape/artifacts/boolean_artifact.py index 7719e9cfe..ac45a1967 100644 --- a/griptape/artifacts/boolean_artifact.py +++ b/griptape/artifacts/boolean_artifact.py @@ -17,9 +17,9 @@ def parse_bool(cls, value: Union[str, bool]) -> BooleanArtifact: if value is not None: if isinstance(value, str): if value.lower() == "true": - return BooleanArtifact(True) + return BooleanArtifact(True) # noqa: FBT003 elif value.lower() == "false": - return BooleanArtifact(False) + return BooleanArtifact(False) # noqa: FBT003 elif isinstance(value, bool): return BooleanArtifact(value) raise ValueError(f"Cannot convert '{value}' to BooleanArtifact") diff --git a/griptape/drivers/event_listener/base_event_listener_driver.py b/griptape/drivers/event_listener/base_event_listener_driver.py index 7792943f3..97d7e5cfa 100644 --- a/griptape/drivers/event_listener/base_event_listener_driver.py +++ b/griptape/drivers/event_listener/base_event_listener_driver.py @@ -28,9 +28,9 @@ class BaseEventListenerDriver(ABC): def batch(self) -> list[dict]: return self._batch - def publish_event(self, event: BaseEvent | dict, flush: bool = False) -> None: + def publish_event(self, event: BaseEvent | dict, *, flush: bool = False) -> None: with self.futures_executor_fn() as executor: - executor.submit(self._safe_try_publish_event, event, flush) + executor.submit(self._safe_try_publish_event, event, flush=flush) @abstractmethod def try_publish_event_payload(self, event_payload: dict) -> None: ... @@ -38,7 +38,7 @@ def try_publish_event_payload(self, event_payload: dict) -> None: ... @abstractmethod def try_publish_event_payload_batch(self, event_payload_batch: list[dict]) -> None: ... - def _safe_try_publish_event(self, event: BaseEvent | dict, flush: bool) -> None: + def _safe_try_publish_event(self, event: BaseEvent | dict, *, flush: bool) -> None: try: event_payload = event if isinstance(event, dict) else event.to_dict() diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 440d6c3c5..09eadace5 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -40,7 +40,7 @@ class AmazonSageMakerJumpstartPromptDriver(BasePromptDriver): ) @stream.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_stream(self, _: Attribute, stream: bool) -> None: + def validate_stream(self, _: Attribute, stream: bool) -> None: # noqa: FBT001 if stream: raise ValueError("streaming is not supported") diff --git a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py index 14e3d81dc..d54b98ec2 100644 --- a/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/amazon_opensearch_vector_store_driver.py @@ -52,6 +52,7 @@ class AmazonOpenSearchVectorStoreDriver(OpenSearchVectorStoreDriver): def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, diff --git a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py index c4c7ef912..60e9df097 100644 --- a/griptape/drivers/vector/azure_mongodb_vector_store_driver.py +++ b/griptape/drivers/vector/azure_mongodb_vector_store_driver.py @@ -14,6 +14,7 @@ class AzureMongoDbVectorStoreDriver(MongoDbAtlasVectorStoreDriver): def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, diff --git a/griptape/drivers/vector/base_vector_store_driver.py b/griptape/drivers/vector/base_vector_store_driver.py index 78407b254..c22285be6 100644 --- a/griptape/drivers/vector/base_vector_store_driver.py +++ b/griptape/drivers/vector/base_vector_store_driver.py @@ -44,18 +44,24 @@ def to_artifact(self) -> BaseArtifact: def upsert_text_artifacts( self, artifacts: list[TextArtifact] | dict[str, list[TextArtifact]], + *, meta: Optional[dict] = None, **kwargs, ) -> None: with self.futures_executor_fn() as executor: if isinstance(artifacts, list): utils.execute_futures_list( - [executor.submit(self.upsert_text_artifact, a, None, meta, **kwargs) for a in artifacts], + [ + executor.submit(self.upsert_text_artifact, a, namespace=None, meta=meta, **kwargs) + for a in artifacts + ], ) else: utils.execute_futures_dict( { - namespace: executor.submit(self.upsert_text_artifact, a, namespace, meta, **kwargs) + namespace: executor.submit( + self.upsert_text_artifact, a, namespace=namespace, meta=meta, **kwargs + ) for namespace, artifact_list in artifacts.items() for a in artifact_list }, @@ -64,6 +70,7 @@ def upsert_text_artifacts( def upsert_text_artifact( self, artifact: TextArtifact, + *, namespace: Optional[str] = None, meta: Optional[dict] = None, vector_id: Optional[str] = None, @@ -75,7 +82,7 @@ def upsert_text_artifact( value = artifact.to_text() if artifact.reference is None else artifact.to_text() + str(artifact.reference) vector_id = self._get_default_vector_id(value) - if self.does_entry_exist(vector_id, namespace): + if self.does_entry_exist(vector_id, namespace=namespace): return vector_id else: meta["artifact"] = artifact.to_json() @@ -90,6 +97,7 @@ def upsert_text_artifact( def upsert_text( self, string: str, + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -97,7 +105,7 @@ def upsert_text( ) -> str: vector_id = self._get_default_vector_id(string) if vector_id is None else vector_id - if self.does_entry_exist(vector_id, namespace): + if self.does_entry_exist(vector_id, namespace=namespace): return vector_id else: return self.upsert_vector( @@ -108,14 +116,14 @@ def upsert_text( **kwargs, ) - def does_entry_exist(self, vector_id: str, namespace: Optional[str] = None) -> bool: + def does_entry_exist(self, vector_id: str, *, namespace: Optional[str] = None) -> bool: try: - return self.load_entry(vector_id, namespace) is not None + return self.load_entry(vector_id, namespace=namespace) is not None except Exception: return False - def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: - result = self.load_entries(namespace) + def load_artifacts(self, *, namespace: Optional[str] = None) -> ListArtifact: + result = self.load_entries(namespace=namespace) artifacts = [r.to_artifact() for r in result] return ListArtifact([a for a in artifacts if isinstance(a, TextArtifact)]) @@ -127,6 +135,7 @@ def delete_vector(self, vector_id: str) -> None: ... def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -134,15 +143,16 @@ def upsert_vector( ) -> str: ... @abstractmethod - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[Entry]: ... + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[Entry]: ... @abstractmethod - def load_entries(self, namespace: Optional[str] = None) -> list[Entry]: ... + def load_entries(self, *, namespace: Optional[str] = None) -> list[Entry]: ... @abstractmethod def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, diff --git a/griptape/drivers/vector/dummy_vector_store_driver.py b/griptape/drivers/vector/dummy_vector_store_driver.py index 2b659ab62..4dbb6c038 100644 --- a/griptape/drivers/vector/dummy_vector_store_driver.py +++ b/griptape/drivers/vector/dummy_vector_store_driver.py @@ -29,15 +29,16 @@ def upsert_vector( ) -> str: raise DummyException(__class__.__name__, "upsert_vector") - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: raise DummyException(__class__.__name__, "load_entry") - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: raise DummyException(__class__.__name__, "load_entries") def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, diff --git a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py index f85f5b9ea..e3bda9d4e 100644 --- a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -67,18 +67,19 @@ def upsert_text( ) -> str: raise NotImplementedError(f"{self.__class__.__name__} does not support text upsert.") - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> BaseVectorStoreDriver.Entry: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> BaseVectorStoreDriver.Entry: raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") - def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: + def load_artifacts(self, *, namespace: Optional[str] = None) -> ListArtifact: raise NotImplementedError(f"{self.__class__.__name__} does not support Artifact loading.") def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: Optional[bool] = None, diff --git a/griptape/drivers/vector/local_vector_store_driver.py b/griptape/drivers/vector/local_vector_store_driver.py index 68fa4561b..ab59f332c 100644 --- a/griptape/drivers/vector/local_vector_store_driver.py +++ b/griptape/drivers/vector/local_vector_store_driver.py @@ -52,6 +52,7 @@ def load_entries_from_file(self, json_file: TextIO) -> dict[str, BaseVectorStore def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -60,7 +61,7 @@ def upsert_vector( vector_id = vector_id if vector_id else utils.str_to_hash(str(vector)) with self.thread_lock: - self.entries[self._namespaced_vector_id(vector_id, namespace)] = self.Entry( + self.entries[self._namespaced_vector_id(vector_id, namespace=namespace)] = self.Entry( id=vector_id, vector=vector, meta=meta, @@ -75,15 +76,16 @@ def upsert_vector( return vector_id - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: - return self.entries.get(self._namespaced_vector_id(vector_id, namespace), None) + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + return self.entries.get(self._namespaced_vector_id(vector_id, namespace=namespace), None) - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: return [entry for key, entry in self.entries.items() if namespace is None or entry.namespace == namespace] def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, @@ -117,5 +119,5 @@ def query( def delete_vector(self, vector_id: str) -> NoReturn: raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") - def _namespaced_vector_id(self, vector_id: str, namespace: Optional[str]) -> str: + def _namespaced_vector_id(self, vector_id: str, *, namespace: Optional[str]) -> str: return vector_id if namespace is None else f"{namespace}-{vector_id}" diff --git a/griptape/drivers/vector/marqo_vector_store_driver.py b/griptape/drivers/vector/marqo_vector_store_driver.py index 38c6f7977..7f6b52103 100644 --- a/griptape/drivers/vector/marqo_vector_store_driver.py +++ b/griptape/drivers/vector/marqo_vector_store_driver.py @@ -39,6 +39,7 @@ class MarqoVectorStoreDriver(BaseVectorStoreDriver): def upsert_text( self, string: str, + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -73,6 +74,7 @@ def upsert_text( def upsert_text_artifact( self, artifact: TextArtifact, + *, namespace: Optional[str] = None, meta: Optional[dict] = None, vector_id: Optional[str] = None, @@ -106,7 +108,7 @@ def upsert_text_artifact( else: raise ValueError(f"Failed to upsert text: {response}") - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: """Load a document entry from the Marqo index. Args: @@ -127,7 +129,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona else: return None - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: """Load all document entries from the Marqo index. Args: @@ -167,6 +169,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, @@ -228,6 +231,7 @@ def get_indexes(self) -> list[str]: def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, diff --git a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py index 26d92e6fd..b17aaf4e7 100644 --- a/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py +++ b/griptape/drivers/vector/mongodb_atlas_vector_store_driver.py @@ -51,6 +51,7 @@ def get_collection(self) -> Collection: def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -73,7 +74,7 @@ def upsert_vector( ) return vector_id - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: """Loads a document entry from the MongoDB collection based on the vector ID. Returns: @@ -95,7 +96,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona meta=doc["meta"], ) - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: """Loads all document entries from the MongoDB collection. Entries can optionally be filtered by namespace. @@ -116,6 +117,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, diff --git a/griptape/drivers/vector/opensearch_vector_store_driver.py b/griptape/drivers/vector/opensearch_vector_store_driver.py index 7f4044e19..403ee18a4 100644 --- a/griptape/drivers/vector/opensearch_vector_store_driver.py +++ b/griptape/drivers/vector/opensearch_vector_store_driver.py @@ -49,6 +49,7 @@ class OpenSearchVectorStoreDriver(BaseVectorStoreDriver): def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -66,7 +67,7 @@ def upsert_vector( return response["_id"] - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: """Retrieves a specific vector entry from OpenSearch based on its identifier and optional namespace. Returns: @@ -95,7 +96,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona logging.error(f"Error while loading entry: {e}") return None - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: """Retrieves all vector entries from OpenSearch that match the optional namespace. Returns: @@ -122,6 +123,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index 2d3d5bf65..f82a5e3ac 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -62,6 +62,7 @@ def __attrs_post_init__(self) -> None: def setup( self, + *, create_schema: bool = True, install_uuid_extension: bool = True, install_vector_extension: bool = True, @@ -79,6 +80,7 @@ def setup( def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -93,7 +95,7 @@ def upsert_vector( return str(getattr(obj, "id")) - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> BaseVectorStoreDriver.Entry: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> BaseVectorStoreDriver.Entry: """Retrieves a specific vector entry from the collection based on its identifier and optional namespace.""" with Session(self.engine) as session: result = session.get(self._model, vector_id) @@ -105,7 +107,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> BaseVec meta=getattr(result, "meta"), ) - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: """Retrieves all vector entries from the collection, optionally filtering to only those that match the provided namespace.""" with Session(self.engine) as session: query = session.query(self._model) @@ -127,6 +129,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD def query( self, query: str, + *, count: Optional[int] = BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, namespace: Optional[str] = None, include_vectors: bool = False, diff --git a/griptape/drivers/vector/pinecone_vector_store_driver.py b/griptape/drivers/vector/pinecone_vector_store_driver.py index 94754317d..028ddebd6 100644 --- a/griptape/drivers/vector/pinecone_vector_store_driver.py +++ b/griptape/drivers/vector/pinecone_vector_store_driver.py @@ -44,7 +44,7 @@ def upsert_vector( return vector_id - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: result = self.index.fetch(ids=[vector_id], namespace=namespace).to_dict() vectors = list(result["vectors"].values()) @@ -60,7 +60,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona else: return None - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: # This is a hacky way to query up to 10,000 values from Pinecone. Waiting on an official API for fetching # all values from a namespace: # https://community.pinecone.io/t/is-there-a-way-to-query-all-the-vectors-and-or-metadata-from-a-namespace/797/5 @@ -85,10 +85,10 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, - # PineconeVectorStorageDriver-specific params: include_metadata: bool = True, **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: diff --git a/griptape/drivers/vector/qdrant_vector_store_driver.py b/griptape/drivers/vector/qdrant_vector_store_driver.py index a92e9a060..4b88b9d5c 100644 --- a/griptape/drivers/vector/qdrant_vector_store_driver.py +++ b/griptape/drivers/vector/qdrant_vector_store_driver.py @@ -89,6 +89,7 @@ def delete_vector(self, vector_id: str) -> None: def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, @@ -127,6 +128,7 @@ def query( def upsert_vector( self, vector: list[float], + *, vector_id: Optional[str] = None, namespace: Optional[str] = None, meta: Optional[dict] = None, @@ -163,7 +165,7 @@ def upsert_vector( self.client.upsert(collection_name=self.collection_name, points=points) return vector_id - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: """Load a vector entry from the Qdrant collection based on its ID. Parameters: @@ -184,7 +186,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona else: return None - def load_entries(self, namespace: Optional[str] = None, **kwargs) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None, **kwargs) -> list[BaseVectorStoreDriver.Entry]: """Load vector entries from the Qdrant collection. Parameters: diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index a676dd908..7d262f05d 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -78,7 +78,7 @@ def upsert_vector( return vector_id - def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: + def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: """Retrieves a specific vector entry from Redis based on its identifier and optional namespace. Returns: @@ -91,7 +91,7 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> Optiona return BaseVectorStoreDriver.Entry(id=vector_id, meta=meta, vector=vector, namespace=namespace) - def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: + def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: """Retrieves all vector entries from Redis that match the optional namespace. Returns: @@ -102,7 +102,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD entries = [] for key in keys: - entry = self.load_entry(key.decode("utf-8"), namespace) + entry = self.load_entry(key.decode("utf-8"), namespace=namespace) if entry: entries.append(entry) @@ -111,6 +111,7 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD def query( self, query: str, + *, count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: bool = False, diff --git a/griptape/events/event_listener.py b/griptape/events/event_listener.py index aee850e08..74171d375 100644 --- a/griptape/events/event_listener.py +++ b/griptape/events/event_listener.py @@ -16,7 +16,7 @@ class EventListener: event_types: Optional[list[type[BaseEvent]]] = field(default=None, kw_only=True) driver: Optional[BaseEventListenerDriver] = field(default=None, kw_only=True) - def publish_event(self, event: BaseEvent, flush: bool = False) -> None: + def publish_event(self, event: BaseEvent, *, flush: bool = False) -> None: event_types = self.event_types if event_types is None or type(event) in event_types: diff --git a/griptape/memory/task/storage/text_artifact_storage.py b/griptape/memory/task/storage/text_artifact_storage.py index 4fdb4011c..8e66c5aba 100644 --- a/griptape/memory/task/storage/text_artifact_storage.py +++ b/griptape/memory/task/storage/text_artifact_storage.py @@ -32,12 +32,12 @@ def can_store(self, artifact: BaseArtifact) -> bool: def store_artifact(self, namespace: str, artifact: BaseArtifact) -> None: if isinstance(artifact, TextArtifact): - self.vector_store_driver.upsert_text_artifact(artifact, namespace) + self.vector_store_driver.upsert_text_artifact(artifact, namespace=namespace) else: raise ValueError("Artifact must be of instance TextArtifact") def load_artifacts(self, namespace: str) -> ListArtifact: - return self.vector_store_driver.load_artifacts(namespace) + return self.vector_store_driver.load_artifacts(namespace=namespace) def summarize(self, namespace: str) -> TextArtifact: if self.summary_engine is None: diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 569accffc..693a98c34 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -25,7 +25,7 @@ class Agent(Structure): fail_fast: bool = field(default=False, kw_only=True) @fail_fast.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_fail_fast(self, _: Attribute, fail_fast: bool) -> None: + def validate_fail_fast(self, _: Attribute, fail_fast: bool) -> None: # noqa: FBT001 if fail_fast: raise ValueError("Agents cannot fail fast, as they can only have 1 task.") diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 5a37c137e..13c247824 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -110,7 +110,7 @@ def validate_embedding_driver(self, attribute: Attribute, value: BaseEmbeddingDr deprecation_warn(f"`{attribute.name}` is deprecated, use `config.embedding_driver` instead.") @stream.validator # pyright: ignore[reportAttributeAccessIssue] - def validate_stream(self, attribute: Attribute, value: bool) -> None: + def validate_stream(self, attribute: Attribute, value: bool) -> None: # noqa: FBT001 if value is not None: deprecation_warn(f"`{attribute.name}` is deprecated, use `config.prompt_driver.stream` instead.") @@ -228,9 +228,9 @@ def remove_event_listener(self, event_listener: EventListener) -> None: else: raise ValueError("Event Listener not found.") - def publish_event(self, event: BaseEvent, flush: bool = False) -> None: + def publish_event(self, event: BaseEvent, *, flush: bool = False) -> None: for event_listener in self.event_listeners: - event_listener.publish_event(event, flush) + event_listener.publish_event(event, flush=True) def context(self, task: BaseTask) -> dict[str, Any]: return {"args": self.execution_args, "structure": self} diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 55dc63033..32485af7b 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -37,6 +37,7 @@ def insert_tasks( parent_tasks: BaseTask | list[BaseTask], tasks: BaseTask | list[BaseTask], child_tasks: BaseTask | list[BaseTask], + *, preserve_relationship: bool = False, ) -> list[BaseTask]: """Insert tasks between parent and child tasks in the workflow. @@ -55,7 +56,7 @@ def insert_tasks( child_tasks = [child_tasks] for task in tasks: - self.insert_task(parent_tasks, task, child_tasks, preserve_relationship) + self.insert_task(parent_tasks, task, child_tasks, preserve_relationship=preserve_relationship) return tasks @@ -64,6 +65,7 @@ def insert_task( parent_tasks: list[BaseTask], task: BaseTask, child_tasks: list[BaseTask], + *, preserve_relationship: bool = False, ) -> BaseTask: task.preprocess(self) diff --git a/griptape/utils/dict_utils.py b/griptape/utils/dict_utils.py index 04be605df..0bf5f59db 100644 --- a/griptape/utils/dict_utils.py +++ b/griptape/utils/dict_utils.py @@ -17,7 +17,7 @@ def remove_key_in_dict_recursively(d: dict, key: str) -> dict: return d -def dict_merge(dct: Optional[dict], merge_dct: Optional[dict], add_keys: bool = True) -> dict: +def dict_merge(dct: Optional[dict], merge_dct: Optional[dict], *, add_keys: bool = True) -> dict: """Recursive dict merge. Inspired by :meth:``dict.update()``, instead of diff --git a/pyproject.toml b/pyproject.toml index 2e094141a..4f9c3b49d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -216,6 +216,7 @@ select = [ "COM", # flake8-commas "C4", # flake8-comprehensions "ANN", # flake8-annotations + "FBT", # flake8-boolean-trap ] ignore = [ "UP007", # non-pep604-annotation diff --git a/tests/unit/drivers/vector/test_base_local_vector_store_driver.py b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py index 6cd1763f6..8c08292dd 100644 --- a/tests/unit/drivers/vector/test_base_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py @@ -41,8 +41,8 @@ def test_upsert_csv_row(self, driver): def test_upsert_multiple(self, driver): driver.upsert_text_artifacts({"foo": [TextArtifact("foo")], "bar": [TextArtifact("bar")]}) - foo_entries = driver.load_entries("foo") - bar_entries = driver.load_entries("bar") + foo_entries = driver.load_entries(namespace="foo") + bar_entries = driver.load_entries(namespace="bar") assert len(driver.entries) == 2 assert foo_entries[0].to_artifact().value == "foo" @@ -70,8 +70,8 @@ def test_load_entries(self, driver): driver.upsert_text_artifact(TextArtifact("foobar 3"), namespace="test-namespace-2") assert len(driver.load_entries()) == 3 - assert len(driver.load_entries("test-namespace-1")) == 2 - assert len(driver.load_entries("test-namespace-2")) == 1 + assert len(driver.load_entries(namespace="test-namespace-1")) == 2 + assert len(driver.load_entries(namespace="test-namespace-2")) == 1 def test_load_artifacts(self, driver): driver.upsert_text_artifact(TextArtifact("foobar 1"), namespace="test-namespace-1") @@ -79,8 +79,8 @@ def test_load_artifacts(self, driver): driver.upsert_text_artifact(TextArtifact("foobar 3"), namespace="test-namespace-2") assert len(driver.load_artifacts()) == 3 - assert len(driver.load_artifacts("test-namespace-1")) == 2 - assert len(driver.load_artifacts("test-namespace-2")) == 1 + assert len(driver.load_artifacts(namespace="test-namespace-1")) == 2 + assert len(driver.load_artifacts(namespace="test-namespace-2")) == 1 def test_does_entry_exist_exception(self, driver): with patch.object(driver, "load_entry", side_effect=Exception): diff --git a/tests/unit/drivers/vector/test_dummy_vector_store_driver.py b/tests/unit/drivers/vector/test_dummy_vector_store_driver.py index abb7f3b38..720778c38 100644 --- a/tests/unit/drivers/vector/test_dummy_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_dummy_vector_store_driver.py @@ -22,7 +22,7 @@ def test_load_entry(self, vector_store_driver): def test_load_entries(self, vector_store_driver): with pytest.raises(DummyException): - vector_store_driver.load_entries("foo bar huzzah") + vector_store_driver.load_entries(namespace="foo bar huzzah") def test_query(self, vector_store_driver): with pytest.raises(DummyException): diff --git a/tests/unit/drivers/vector/test_local_vector_store_driver.py b/tests/unit/drivers/vector/test_local_vector_store_driver.py index 937f14ece..314f2fd6d 100644 --- a/tests/unit/drivers/vector/test_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_local_vector_store_driver.py @@ -13,11 +13,11 @@ def driver(self): def test_upsert_text_artifacts_dict(self, driver): driver.upsert_text_artifacts({"foo": [TextArtifact("bar"), TextArtifact("baz")], "bar": [TextArtifact("bar")]}) - assert len(driver.load_artifacts("foo")) == 2 - assert len(driver.load_artifacts("bar")) == 1 + assert len(driver.load_artifacts(namespace="foo")) == 2 + assert len(driver.load_artifacts(namespace="bar")) == 1 def test_upsert_text_artifacts_list(self, driver): driver.upsert_text_artifacts([TextArtifact("bar"), TextArtifact("baz")]) - assert len(driver.load_artifacts("foo")) == 0 + assert len(driver.load_artifacts(namespace="foo")) == 0 assert len(driver.load_artifacts()) == 2 diff --git a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py index c999af8b9..8abfbf4f7 100644 --- a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py @@ -93,7 +93,7 @@ def test_query(self, driver): count = 10 include_vectors = True - results = driver.query(query, count, include_vectors=include_vectors) + results = driver.query(query, count=count, include_vectors=include_vectors) mock_embed.assert_called_once_with(query) mock_search.assert_called_once_with( From 974a3cb1626e8c75ea9a44f58dbd5b12b04e38f1 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 16 Jul 2024 11:19:52 -0700 Subject: [PATCH 74/87] Run ruff on entire project (#986) --- Makefile | 8 ++-- docs/gen_ref_pages.py | 9 ++-- docs/plugins/swagger_ui_plugin.py | 9 ++-- pyproject.toml | 11 ++++- .../test_pgvector_vector_store_driver.py | 25 +++++------ tests/integration/rules/test_rule.py | 5 ++- .../tasks/test_csv_extraction_task.py | 7 ++-- .../tasks/test_json_extraction_task.py | 10 +++-- tests/integration/tasks/test_prompt_task.py | 3 +- tests/integration/tasks/test_rag_task.py | 7 ++-- .../tasks/test_text_summary_task.py | 29 ++++++------- tests/integration/tasks/test_tool_task.py | 3 +- tests/integration/tasks/test_toolkit_task.py | 8 ++-- tests/integration/test_code_blocks.py | 2 +- tests/integration/tools/test_calculator.py | 3 +- tests/integration/tools/test_file_manager.py | 3 +- .../tools/test_google_docs_client.py | 4 +- .../tools/test_google_drive_client.py | 4 +- tests/mocks/docker/fake_api.py | 17 ++++---- tests/mocks/docker/fake_api_client.py | 15 +++---- tests/mocks/invalid_mock_tool/tool.py | 3 +- tests/mocks/mock_audio_input_task.py | 1 + tests/mocks/mock_embedding_driver.py | 5 ++- tests/mocks/mock_event_listener_driver.py | 2 + tests/mocks/mock_failing_prompt_driver.py | 9 +++- tests/mocks/mock_image_generation_driver.py | 4 ++ tests/mocks/mock_image_generation_task.py | 2 +- tests/mocks/mock_image_query_driver.py | 5 ++- tests/mocks/mock_multi_text_input_task.py | 1 + tests/mocks/mock_prompt_driver.py | 12 +++--- tests/mocks/mock_serializable.py | 10 ++++- tests/mocks/mock_structure_config.py | 5 ++- tests/mocks/mock_task.py | 3 +- tests/mocks/mock_text_input_task.py | 1 + tests/mocks/mock_tokenizer.py | 2 + tests/mocks/mock_tool/tool.py | 7 ++-- tests/unit/artifacts/test_action_artifact.py | 6 ++- tests/unit/artifacts/test_audio_artifact.py | 3 +- tests/unit/artifacts/test_base_artifact.py | 7 ++-- .../artifacts/test_base_media_artifact.py | 3 +- tests/unit/artifacts/test_blob_artifact.py | 4 +- tests/unit/artifacts/test_boolean_artifact.py | 10 +++-- tests/unit/artifacts/test_image_artifact.py | 5 ++- tests/unit/artifacts/test_list_artifact.py | 3 +- tests/unit/artifacts/test_text_artifact.py | 4 +- tests/unit/chunkers/test_markdown_chunker.py | 3 +- tests/unit/chunkers/test_pdf_chunker.py | 4 +- tests/unit/chunkers/test_text_chunker.py | 3 +- tests/unit/chunkers/utils.py | 4 +- .../test_action_call_message_content.py | 3 +- .../test_action_result_message_content.py | 1 + .../contents/test_image_message_content.py | 1 + .../contents/test_text_message_content.py | 2 +- tests/unit/common/test_action.py | 4 +- tests/unit/common/test_prompt_stack.py | 15 ++++--- .../test_amazon_bedrock_structure_config.py | 11 ++--- .../config/test_anthropic_structure_config.py | 9 ++-- .../test_azure_openai_structure_config.py | 7 ++-- .../config/test_cohere_structure_config.py | 5 ++- .../config/test_google_structure_config.py | 7 ++-- .../config/test_openai_structure_config.py | 7 ++-- tests/unit/config/test_structure_config.py | 5 ++- ..._amazon_bedrock_cohere_embedding_driver.py | 6 ++- ...t_amazon_bedrock_titan_embedding_driver.py | 6 ++- .../test_azure_openai_embedding_driver.py | 4 +- .../embedding/test_base_embedding_driver.py | 6 ++- .../embedding/test_cohere_embedding_driver.py | 2 + .../embedding/test_dummy_embedding_driver.py | 4 +- .../embedding/test_google_embedding_driver.py | 2 + .../embedding/test_ollama_embedding_driver.py | 1 + .../embedding/test_openai_embedding_driver.py | 4 +- ...st_sagemaker_jumpstart_embedding_driver.py | 10 ++--- .../test_voyageai_embedding_driver.py | 4 +- .../test_amazon_sqs_event_listener_driver.py | 13 +++--- .../test_aws_iot_event_listener_driver.py | 13 +++--- .../test_base_event_listener_driver.py | 1 + ...st_griptape_cloud_event_listener_driver.py | 5 +-- .../test_pusher_event_listener_driver.py | 12 +++--- .../test_webhook_event_listener_driver.py | 8 ++-- .../test_amazon_s3_file_manager_driver.py | 41 +++++++++---------- .../test_local_file_manager_driver.py | 26 ++++++------ ...table_diffusion_image_generation_driver.py | 10 ++--- ...st_azure_openai_image_generation_driver.py | 8 ++-- .../test_dummy_image_generation_driver.py | 6 +-- .../test_leonardo_image_generation_driver.py | 6 ++- .../test_openai_image_generation_driver.py | 6 ++- ...ock_stable_diffusion_image_model_driver.py | 8 ++-- .../test_bedrock_titan_image_model_driver.py | 6 +-- .../test_amazon_bedrock_image_query_driver.py | 14 ++++--- .../test_anthropic_image_query_driver.py | 10 +++-- .../test_azure_openai_image_query_driver.py | 10 +++-- .../test_dummy_image_query_driver.py | 6 +-- .../test_openai_image_query_driver.py | 10 +++-- ...bedrock_claude_image_query_model_driver.py | 3 +- ...est_dynamodb_conversation_memory_driver.py | 13 +++--- .../test_local_conversation_memory_driver.py | 17 ++++---- .../test_redis_conversation_memory_driver.py | 9 ++-- .../test_amazon_bedrock_prompt_driver.py | 12 +++--- ...mazon_sagemaker_jumpstart_prompt_driver.py | 12 +++--- .../prompt/test_anthropic_prompt_driver.py | 15 +++---- .../test_azure_openai_chat_prompt_driver.py | 12 +++--- .../drivers/prompt/test_base_prompt_driver.py | 10 ++--- .../prompt/test_cohere_prompt_driver.py | 7 ++-- .../prompt/test_dummy_prompt_driver.py | 4 +- .../prompt/test_google_prompt_driver.py | 22 +++++----- .../test_hugging_face_hub_prompt_driver.py | 11 ++--- ...est_hugging_face_pipeline_prompt_driver.py | 7 ++-- .../prompt/test_ollama_prompt_driver.py | 11 ++--- .../prompt/test_openai_chat_prompt_driver.py | 21 +++++----- .../rerank/test_cohere_rerank_driver.py | 5 ++- .../sql/test_amazon_redshift_sql_driver.py | 9 ++-- .../drivers/sql/test_snowflake_sql_driver.py | 18 ++++---- tests/unit/drivers/sql/test_sql_driver.py | 3 +- ...est_griptape_cloud_structure_run_driver.py | 5 ++- .../test_local_structure_run_driver.py | 12 +++--- ...test_elevenlabs_audio_generation_driver.py | 6 ++- .../test_openai_audio_transcription_driver.py | 7 ++-- ...t_amazon_opensearch_vector_store_driver.py | 10 +++-- .../test_azure_mongodb_vector_store_driver.py | 16 ++++---- .../test_base_local_vector_store_driver.py | 6 ++- .../vector/test_dummy_vector_store_driver.py | 3 +- ...loud_knowledge_base_vector_store_driver.py | 6 ++- .../vector/test_local_vector_store_driver.py | 3 +- .../vector/test_marqo_vector_store_driver.py | 6 ++- .../test_mongodb_atlas_vector_store_driver.py | 18 ++++---- .../test_opensearch_vector_store_driver.py | 8 ++-- ...st_persistent_local_vector_store_driver.py | 6 ++- .../test_pgvector_vector_store_driver.py | 20 +++++---- .../test_pinecone_vector_storage_driver.py | 10 +---- .../vector/test_qdrant_vector_store_driver.py | 12 +++--- .../vector/test_redis_vector_store_driver.py | 12 +++--- .../test_markdownify_web_scraper_driver.py | 17 ++++---- .../test_proxy_web_scraper_driver.py | 8 ++-- .../test_trafilatura_web_scraper_driver.py | 4 +- .../test_duck_duck_go_web_search_driver.py | 10 +++-- .../test_google_web_search_driver.py | 12 +++--- .../extraction/test_csv_extraction_engine.py | 3 +- .../extraction/test_json_extraction_engine.py | 3 +- ...est_footnote_prompt_response_rag_module.py | 3 +- .../test_prompt_response_rag_module.py | 3 +- ...est_rulesets_before_response_rag_module.py | 2 +- .../test_text_chunks_response_rag_module.py | 3 +- .../test_text_chunks_rerank_rag_module.py | 3 +- .../test_text_loader_retrieval_rag_module.py | 2 +- tests/unit/engines/rag/test_rag_engine.py | 9 ++-- .../summary/test_prompt_summary_engine.py | 10 +++-- tests/unit/events/test_base_event.py | 14 ++++--- .../events/test_completion_chunk_event.py | 3 +- tests/unit/events/test_event_listener.py | 26 ++++++------ .../test_finish_actions_subtask_event.py | 3 +- tests/unit/events/test_finish_prompt_event.py | 3 +- .../events/test_finish_structure_run_event.py | 2 +- tests/unit/events/test_finish_task_event.py | 5 ++- .../test_start_actions_subtask_event.py | 3 +- tests/unit/events/test_start_prompt_event.py | 5 ++- .../events/test_start_structure_run_event.py | 3 +- tests/unit/events/test_start_task_event.py | 3 +- tests/unit/loaders/conftest.py | 6 +-- tests/unit/loaders/test_audio_loader.py | 9 ++-- tests/unit/loaders/test_blob_loader.py | 1 + tests/unit/loaders/test_csv_loader.py | 3 +- tests/unit/loaders/test_dataframe_loader.py | 5 ++- tests/unit/loaders/test_email_loader.py | 14 ++++--- tests/unit/loaders/test_image_loader.py | 8 ++-- tests/unit/loaders/test_pdf_loader.py | 9 ++-- tests/unit/loaders/test_sql_loader.py | 3 +- tests/unit/loaders/test_text_loader.py | 1 + tests/unit/loaders/test_web_loader.py | 5 ++- .../meta/test_action_subtask_meta_entry.py | 3 +- tests/unit/memory/meta/test_meta_memory.py | 5 ++- .../structure/test_conversation_memory.py | 10 ++--- .../test_summary_conversation_memory.py | 3 +- .../storage/test_blob_artifact_storage.py | 3 +- .../storage/test_text_artifact_storage.py | 3 +- tests/unit/memory/tool/test_task_memory.py | 8 ++-- tests/unit/mixins/test_activity_mixin.py | 5 ++- .../test_image_artifact_file_output_mixin.py | 4 +- tests/unit/mixins/test_seriliazable_mixin.py | 8 ++-- tests/unit/schemas/test_base_schema.py | 13 +++--- tests/unit/structures/test_agent.py | 16 ++++---- tests/unit/structures/test_pipeline.py | 17 ++++---- tests/unit/structures/test_workflow.py | 28 ++++++------- tests/unit/tasks/test_actions_subtask.py | 9 ++-- .../tasks/test_audio_transcription_task.py | 13 ++---- .../unit/tasks/test_base_audio_input_task.py | 4 +- .../tasks/test_base_multi_text_input_task.py | 4 +- tests/unit/tasks/test_base_task.py | 5 +-- tests/unit/tasks/test_base_text_input_task.py | 6 +-- tests/unit/tasks/test_code_execution_task.py | 2 +- tests/unit/tasks/test_csv_extraction_task.py | 4 +- tests/unit/tasks/test_extraction_task.py | 3 +- tests/unit/tasks/test_image_query_task.py | 8 ++-- .../test_inpainting_image_generation_task.py | 15 +++---- tests/unit/tasks/test_json_extraction_task.py | 9 ++-- .../test_outpainting_image_generation_task.py | 10 ++--- .../test_prompt_image_generation_task.py | 4 +- tests/unit/tasks/test_prompt_task.py | 9 ++-- tests/unit/tasks/test_rag_task.py | 3 +- tests/unit/tasks/test_structure_run_task.py | 5 +-- tests/unit/tasks/test_text_summary_task.py | 7 ++-- tests/unit/tasks/test_text_to_speech_task.py | 2 +- tests/unit/tasks/test_tool_task.py | 6 ++- tests/unit/tasks/test_toolkit_task.py | 10 ++--- .../test_variation_image_generation_task.py | 17 ++++---- .../test_amazon_bedrock_tokenizer.py | 11 ++--- .../tokenizers/test_anthropic_tokenizer.py | 9 ++-- tests/unit/tokenizers/test_base_tokenizer.py | 1 + .../unit/tokenizers/test_cohere_tokenizer.py | 3 +- tests/unit/tokenizers/test_dummy_tokenizer.py | 3 +- .../unit/tokenizers/test_google_tokenizer.py | 12 +++--- .../tokenizers/test_hugging_face_tokenizer.py | 3 +- .../unit/tokenizers/test_openai_tokenizer.py | 14 +++---- .../unit/tokenizers/test_simple_tokenizer.py | 3 +- .../tokenizers/test_voyageai_tokenizer.py | 9 ++-- tests/unit/tools/test_aws_iam.py | 9 ++-- tests/unit/tools/test_aws_s3.py | 9 ++-- tests/unit/tools/test_base_tool.py | 14 ++++--- tests/unit/tools/test_computer.py | 5 ++- tests/unit/tools/test_date_time.py | 3 +- tests/unit/tools/test_email_client.py | 12 +++--- tests/unit/tools/test_file_manager.py | 10 +++-- tests/unit/tools/test_google_docs_client.py | 2 +- tests/unit/tools/test_google_drive_client.py | 2 +- ...st_griptape_cloud_knowledge_base_client.py | 15 +++---- ...test_inpainting_image_generation_client.py | 8 ++-- tests/unit/tools/test_openweather_client.py | 8 ++-- ...test_outpainting_image_variation_client.py | 8 ++-- .../test_prompt_image_generation_client.py | 6 +-- tests/unit/tools/test_rest_api_client.py | 3 +- tests/unit/tools/test_sql_client.py | 6 ++- tests/unit/tools/test_structure_run_client.py | 5 ++- tests/unit/tools/test_task_memory_client.py | 3 +- .../unit/tools/test_text_to_speech_client.py | 6 +-- tests/unit/tools/test_transcription_client.py | 8 ++-- .../test_variation_image_generation_client.py | 8 ++-- tests/unit/tools/test_vector_store_client.py | 7 ++-- tests/unit/tools/test_web_scraper.py | 3 +- tests/unit/tools/test_web_search.py | 5 ++- tests/unit/utils/test_base_tokenizer.py | 1 + tests/unit/utils/test_command_runner.py | 1 - tests/unit/utils/test_conversation.py | 4 +- tests/unit/utils/test_deprecate.py | 1 + tests/unit/utils/test_dict_utils.py | 3 +- tests/unit/utils/test_file_utils.py | 5 ++- tests/unit/utils/test_futures.py | 1 + tests/unit/utils/test_import_utils.py | 1 + .../utils/test_load_artifact_from_memory.py | 22 ++++------ tests/unit/utils/test_message_stack.py | 2 +- tests/unit/utils/test_stream.py | 6 ++- tests/unit/utils/test_structure_visualizer.py | 6 +-- tests/utils/code_blocks.py | 4 +- tests/utils/defaults.py | 10 ++--- tests/utils/postgres.py | 2 +- tests/utils/structure_tester.py | 29 ++++++------- 254 files changed, 1059 insertions(+), 824 deletions(-) diff --git a/Makefile b/Makefile index 13410094c..d14c7184d 100644 --- a/Makefile +++ b/Makefile @@ -33,22 +33,22 @@ test/integration: .PHONY: lint lint: ## Lint project. - @poetry run ruff check --fix griptape/ + @poetry run ruff check --fix .PHONY: format format: ## Format project. - @poetry run ruff format . + @poetry run ruff format .PHONY: check check: check/format check/lint check/types check/spell ## Run all checks. .PHONY: check/format check/format: - @poetry run ruff format --check griptape/ + @poetry run ruff format --check .PHONY: check/lint check/lint: - @poetry run ruff check griptape/ + @poetry run ruff check .PHONY: check/types check/types: diff --git a/docs/gen_ref_pages.py b/docs/gen_ref_pages.py index 62fe85b0c..85a3f3127 100644 --- a/docs/gen_ref_pages.py +++ b/docs/gen_ref_pages.py @@ -1,11 +1,12 @@ """Generate the code reference pages and navigation.""" -from textwrap import dedent from pathlib import Path +from textwrap import dedent + import mkdocs_gen_files -def build_reference_docs(): +def build_reference_docs() -> None: nav = mkdocs_gen_files.Nav() for path in sorted(Path("griptape").rglob("*.py")): @@ -37,8 +38,8 @@ def build_reference_docs(): index_file.write( dedent( """ - # Overview - This section of the documentation is dedicated to a reference API of Griptape. + # Overview + This section of the documentation is dedicated to a reference API of Griptape. Here you will find every class, function, and method that is available to you when using the library. """ ) diff --git a/docs/plugins/swagger_ui_plugin.py b/docs/plugins/swagger_ui_plugin.py index 6d5fb52da..499d74cf5 100644 --- a/docs/plugins/swagger_ui_plugin.py +++ b/docs/plugins/swagger_ui_plugin.py @@ -1,4 +1,5 @@ import os +from typing import Any import markdown from jinja2 import Environment, FileSystemLoader, select_autoescape @@ -11,7 +12,7 @@ } -def generate_page_contents(page): +def generate_page_contents(page: Any) -> str: spec_url = config_scheme["spec_url"] tmpl_url = config_scheme["template"] env = Environment(loader=FileSystemLoader("docs/plugins/tmpl"), autoescape=select_autoescape(["html", "xml"])) @@ -23,11 +24,11 @@ def generate_page_contents(page): return tmpl_out -def on_config(config): - print("INFO - swagger-ui plugin ENABLED") +def on_config(config: Any) -> None: + pass -def on_page_read_source(page, config): +def on_page_read_source(page: Any, config: Any) -> Any: index_path = os.path.join(config["docs_dir"], config_scheme["outfile"]) page_path = os.path.join(config["docs_dir"], page.file.src_path) if index_path == page_path: diff --git a/pyproject.toml b/pyproject.toml index 4f9c3b49d..807a2560e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -217,6 +217,7 @@ select = [ "C4", # flake8-comprehensions "ANN", # flake8-annotations "FBT", # flake8-boolean-trap + "PT", # flake8-pytest-style ] ignore = [ "UP007", # non-pep604-annotation @@ -238,12 +239,20 @@ ignore = [ "ANN101", # missing-type-self "ANN102", # missing-type-cls "ANN401", # any-type + "PT011", # pytest-raises-too-broad ] [tool.ruff.lint.pydocstyle] convention = "google" [tool.ruff.lint.per-file-ignores] -"__init__.py" = ["I"] +"__init__.py" = [ + "I" # isort +] +"tests/*" = [ + "ANN001", # missing-type-function-argument + "ANN201", # missing-return-type-undocumented-public-function + "ANN202", # missing-return-type-private-function +] [tool.ruff.lint.flake8-tidy-imports.banned-api] "attr".msg = "The attr module is deprecated, use attrs instead." diff --git a/tests/integration/drivers/vector/test_pgvector_vector_store_driver.py b/tests/integration/drivers/vector/test_pgvector_vector_store_driver.py index e0345cecb..e592fce06 100644 --- a/tests/integration/drivers/vector/test_pgvector_vector_store_driver.py +++ b/tests/integration/drivers/vector/test_pgvector_vector_store_driver.py @@ -1,9 +1,11 @@ import uuid + import pytest +from sqlalchemy import create_engine + from griptape.drivers import PgVectorVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.utils.postgres import can_connect_to_postgres -from sqlalchemy import create_engine @pytest.mark.skipif(not can_connect_to_postgres(), reason="Postgres is not present") @@ -13,11 +15,11 @@ class TestPgVectorVectorStoreDriver: vec1 = [0.1, 0.2, 0.3] vec2 = [0.4, 0.5, 0.6] - @pytest.fixture + @pytest.fixture() def embedding_driver(self): return MockEmbeddingDriver() - @pytest.fixture + @pytest.fixture() def vector_store_driver(self, embedding_driver): driver = PgVectorVectorStoreDriver( connection_string=self.connection_string, embedding_driver=embedding_driver, table_name=self.table_name @@ -28,13 +30,13 @@ def vector_store_driver(self, embedding_driver): return driver def test_initialize_requires_engine_or_connection_string(self, embedding_driver): + driver = PgVectorVectorStoreDriver(embedding_driver=embedding_driver, table_name=self.table_name) with pytest.raises(ValueError): - driver = PgVectorVectorStoreDriver(embedding_driver=embedding_driver, table_name=self.table_name) driver.setup() def test_initialize_accepts_engine(self, embedding_driver): engine = create_engine(self.connection_string) - driver = PgVectorVectorStoreDriver(embedding_driver=embedding_driver, engine=engine, table_name=self.table_name) + driver = PgVectorVectorStoreDriver(embedding_driver=embedding_driver, engine=engine, table_name=self.table_name) # pyright: ignore[reportArgumentType] driver.setup() @@ -86,11 +88,9 @@ def test_can_insert_and_load_entry_with_namespace(self, vector_store_driver): assert result.vector == pytest.approx(self.vec1) def test_can_load_entries(self, vector_store_driver): - """ - Depending on when this test is executed relative to the others, - we don't know exactly how many vectors will be returned. We can - ensure that at least two exist and confirm that those are found. - """ + # Depending on when this test is executed relative to the others, + # we don't know exactly how many vectors will be returned. We can + # ensure that at least two exist and confirm that those are found. vec1_id = vector_store_driver.upsert_vector(self.vec1) vec2_id = vector_store_driver.upsert_vector(self.vec2) @@ -173,8 +173,9 @@ def test_query_returns_vectors_when_requested(self, vector_store_driver): assert results[0].vector == pytest.approx(embedding) def test_can_use_custom_table_name(self, embedding_driver, vector_store_driver): - """This test ensures at least one row exists in the default table before specifying - a custom table name. After inserting another row, we should be able to query only one + """This test ensures at least one row exists in the default table before specifying a custom table name. + + After inserting another row, we should be able to query only one vector from the table, and it should be the vector added to the table with the new name. """ vector_store_driver.upsert_vector(self.vec1) diff --git a/tests/integration/rules/test_rule.py b/tests/integration/rules/test_rule.py index f04996040..a62263c57 100644 --- a/tests/integration/rules/test_rule.py +++ b/tests/integration/rules/test_rule.py @@ -1,14 +1,15 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestRule: @pytest.fixture( autouse=True, params=StructureTester.RULE_CAPABLE_PROMPT_DRIVERS, ids=StructureTester.prompt_driver_id_fn ) def structure_tester(self, request): - from griptape.structures import Agent from griptape.rules import Rule + from griptape.structures import Agent agent = Agent(prompt_driver=request.param, rules=[Rule("Your name is Tony.")]) diff --git a/tests/integration/tasks/test_csv_extraction_task.py b/tests/integration/tasks/test_csv_extraction_task.py index 4624431ca..db58b9615 100644 --- a/tests/integration/tasks/test_csv_extraction_task.py +++ b/tests/integration/tasks/test_csv_extraction_task.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestCsvExtractionTask: @pytest.fixture( @@ -9,9 +10,9 @@ class TestCsvExtractionTask: ids=StructureTester.prompt_driver_id_fn, ) def structure_tester(self, request): - from griptape.tasks import ExtractionTask - from griptape.structures import Agent from griptape.engines import CsvExtractionEngine + from griptape.structures import Agent + from griptape.tasks import ExtractionTask columns = ["Name", "Age", "Address"] diff --git a/tests/integration/tasks/test_json_extraction_task.py b/tests/integration/tasks/test_json_extraction_task.py index fdd7140f3..115f805da 100644 --- a/tests/integration/tasks/test_json_extraction_task.py +++ b/tests/integration/tasks/test_json_extraction_task.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestJsonExtractionTask: @pytest.fixture( @@ -9,11 +10,12 @@ class TestJsonExtractionTask: ids=StructureTester.prompt_driver_id_fn, ) def structure_tester(self, request): - from griptape.tasks import ExtractionTask - from griptape.structures import Agent - from griptape.engines import JsonExtractionEngine from schema import Schema + from griptape.engines import JsonExtractionEngine + from griptape.structures import Agent + from griptape.tasks import ExtractionTask + # Define some JSON data user_schema = Schema({"users": [{"name": str, "age": int, "location": str}]}).json_schema("UserSchema") diff --git a/tests/integration/tasks/test_prompt_task.py b/tests/integration/tasks/test_prompt_task.py index 6734df678..1d223b4ca 100644 --- a/tests/integration/tasks/test_prompt_task.py +++ b/tests/integration/tasks/test_prompt_task.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestPromptTask: @pytest.fixture( diff --git a/tests/integration/tasks/test_rag_task.py b/tests/integration/tasks/test_rag_task.py index c0383002c..ce3a9140d 100644 --- a/tests/integration/tasks/test_rag_task.py +++ b/tests/integration/tasks/test_rag_task.py @@ -1,7 +1,8 @@ +import pytest + from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.utils.defaults import rag_engine from tests.utils.structure_tester import StructureTester -import pytest class TestRagTask: @@ -11,10 +12,10 @@ class TestRagTask: ids=StructureTester.prompt_driver_id_fn, ) def structure_tester(self, request): + from griptape.artifacts import TextArtifact + from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver from griptape.structures import Agent from griptape.tasks import RagTask - from griptape.drivers import LocalVectorStoreDriver, OpenAiEmbeddingDriver - from griptape.artifacts import TextArtifact vector_store_driver = LocalVectorStoreDriver(embedding_driver=OpenAiEmbeddingDriver()) artifact = TextArtifact("John Doe works as as software engineer at Griptape.") diff --git a/tests/integration/tasks/test_text_summary_task.py b/tests/integration/tasks/test_text_summary_task.py index 9cbf1d905..ff6597ba0 100644 --- a/tests/integration/tasks/test_text_summary_task.py +++ b/tests/integration/tasks/test_text_summary_task.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestTextSummaryTask: @pytest.fixture( @@ -10,8 +11,8 @@ class TestTextSummaryTask: ) def structure_tester(self, request): from griptape.engines.summary.prompt_summary_engine import PromptSummaryEngine - from griptape.tasks import TextSummaryTask from griptape.structures import Agent + from griptape.tasks import TextSummaryTask agent = Agent(conversation_memory=None, prompt_driver=request.param) agent.add_task(TextSummaryTask(summary_engine=PromptSummaryEngine(prompt_driver=request.param))) @@ -21,17 +22,17 @@ def structure_tester(self, request): def test_summary_task(self, structure_tester): structure_tester.run( """ - Meeting transcriot: - Miguel: Hi Brant, I want to discuss the workstream for our new product launch - Brant: Sure Miguel, is there anything in particular you want to discuss? - Miguel: Yes, I want to talk about how users enter into the product. - Brant: Ok, in that case let me add in Namita. - Namita: Hey everyone - Brant: Hi Namita, Miguel wants to discuss how users enter into the product. - Miguel: its too complicated and we should remove friction. for example, why do I need to fill out additional forms? I also find it difficult to find where to access the product when I first land on the landing page. - Brant: I would also add that I think there are too many steps. - Namita: Ok, I can work on the landing page to make the product more discoverable but brant can you work on the additional forms? - Brant: Yes but I would need to work with James from another team as he needs to unblock the sign up workflow. Miguel can you document any other concerns so that I can discuss with James only once? - Miguel: Sure. + Meeting transcriot: + Miguel: Hi Brant, I want to discuss the workstream for our new product launch + Brant: Sure Miguel, is there anything in particular you want to discuss? + Miguel: Yes, I want to talk about how users enter into the product. + Brant: Ok, in that case let me add in Namita. + Namita: Hey everyone + Brant: Hi Namita, Miguel wants to discuss how users enter into the product. + Miguel: its too complicated and we should remove friction. for example, why do I need to fill out additional forms? I also find it difficult to find where to access the product when I first land on the landing page. + Brant: I would also add that I think there are too many steps. + Namita: Ok, I can work on the landing page to make the product more discoverable but brant can you work on the additional forms? + Brant: Yes but I would need to work with James from another team as he needs to unblock the sign up workflow. Miguel can you document any other concerns so that I can discuss with James only once? + Miguel: Sure. """ ) diff --git a/tests/integration/tasks/test_tool_task.py b/tests/integration/tasks/test_tool_task.py index 1fa48e98d..aee0af110 100644 --- a/tests/integration/tasks/test_tool_task.py +++ b/tests/integration/tasks/test_tool_task.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestToolTask: @pytest.fixture( diff --git a/tests/integration/tasks/test_toolkit_task.py b/tests/integration/tasks/test_toolkit_task.py index a4d8c30c3..8dfcfdc73 100644 --- a/tests/integration/tasks/test_toolkit_task.py +++ b/tests/integration/tasks/test_toolkit_task.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestToolkitTask: @pytest.fixture( @@ -10,9 +11,10 @@ class TestToolkitTask: ) def structure_tester(self, request): import os - from griptape.structures import Agent - from griptape.tools import WebScraper, WebSearch, TaskMemoryClient + from griptape.drivers import GoogleWebSearchDriver + from griptape.structures import Agent + from griptape.tools import TaskMemoryClient, WebScraper, WebSearch return StructureTester( Agent( diff --git a/tests/integration/test_code_blocks.py b/tests/integration/test_code_blocks.py index 3a267a529..2da683a2a 100644 --- a/tests/integration/test_code_blocks.py +++ b/tests/integration/test_code_blocks.py @@ -2,8 +2,8 @@ import os import pytest -from tests.utils.code_blocks import get_all_code_blocks, check_py_string +from tests.utils.code_blocks import check_py_string, get_all_code_blocks if "DOCS_ALL_CHANGED_FILES" in os.environ and os.environ["DOCS_ALL_CHANGED_FILES"] != "": docs_all_changed_files = os.environ["DOCS_ALL_CHANGED_FILES"].split() diff --git a/tests/integration/tools/test_calculator.py b/tests/integration/tools/test_calculator.py index 9015c7158..2547b947d 100644 --- a/tests/integration/tools/test_calculator.py +++ b/tests/integration/tools/test_calculator.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestCalculator: @pytest.fixture( diff --git a/tests/integration/tools/test_file_manager.py b/tests/integration/tools/test_file_manager.py index 462e66470..8a283c6e8 100644 --- a/tests/integration/tools/test_file_manager.py +++ b/tests/integration/tools/test_file_manager.py @@ -1,6 +1,7 @@ -from tests.utils.structure_tester import StructureTester import pytest +from tests.utils.structure_tester import StructureTester + class TestFileManager: @pytest.fixture( diff --git a/tests/integration/tools/test_google_docs_client.py b/tests/integration/tools/test_google_docs_client.py index dfb1eb95b..4d70aac17 100644 --- a/tests/integration/tools/test_google_docs_client.py +++ b/tests/integration/tools/test_google_docs_client.py @@ -1,5 +1,7 @@ -import pytest import os + +import pytest + from tests.utils.structure_tester import StructureTester diff --git a/tests/integration/tools/test_google_drive_client.py b/tests/integration/tools/test_google_drive_client.py index 9bbbacfb5..23ebb1b32 100644 --- a/tests/integration/tools/test_google_drive_client.py +++ b/tests/integration/tools/test_google_drive_client.py @@ -1,5 +1,7 @@ -import pytest import os + +import pytest + from tests.utils.structure_tester import StructureTester diff --git a/tests/mocks/docker/fake_api.py b/tests/mocks/docker/fake_api.py index 3d5a411e5..881093057 100644 --- a/tests/mocks/docker/fake_api.py +++ b/tests/mocks/docker/fake_api.py @@ -150,7 +150,7 @@ def post_fake_create_container(): return status_code, response -def get_fake_inspect_container(tty=False): +def get_fake_inspect_container(*, tty=False): status_code = 200 response = { "Id": FAKE_CONTAINER_ID, @@ -531,7 +531,6 @@ def post_fake_secret(): f"{prefix}/{CURRENT_VERSION}/containers/{FAKE_CONTAINER_ID}/unpause": post_fake_unpause_container, f"{prefix}/{CURRENT_VERSION}/containers/{FAKE_CONTAINER_ID}/restart": post_fake_restart_container, f"{prefix}/{CURRENT_VERSION}/containers/{FAKE_CONTAINER_ID}": delete_fake_remove_container, - f"{prefix}/{CURRENT_VERSION}/images/create": post_fake_image_create, f"{prefix}/{CURRENT_VERSION}/images/{FAKE_IMAGE_ID}": delete_fake_remove_image, f"{prefix}/{CURRENT_VERSION}/images/{FAKE_IMAGE_ID}/get": get_fake_get_image, f"{prefix}/{CURRENT_VERSION}/images/load": post_fake_load_image, @@ -544,20 +543,20 @@ def post_fake_secret(): f"{prefix}/{CURRENT_VERSION}/events": get_fake_events, (f"{prefix}/{CURRENT_VERSION}/volumes", "GET"): get_fake_volume_list, (f"{prefix}/{CURRENT_VERSION}/volumes/create", "POST"): get_fake_volume, - ("{1}/{0}/volumes/{2}".format(CURRENT_VERSION, prefix, FAKE_VOLUME_NAME), "GET"): get_fake_volume, - ("{1}/{0}/volumes/{2}".format(CURRENT_VERSION, prefix, FAKE_VOLUME_NAME), "DELETE"): fake_remove_volume, - ("{1}/{0}/nodes/{2}/update?version=1".format(CURRENT_VERSION, prefix, FAKE_NODE_ID), "POST"): post_fake_update_node, + (f"{prefix}/{CURRENT_VERSION}/volumes/{FAKE_VOLUME_NAME}", "GET"): get_fake_volume, + (f"{prefix}/{CURRENT_VERSION}/volumes/{FAKE_VOLUME_NAME}", "DELETE"): fake_remove_volume, + (f"{prefix}/{CURRENT_VERSION}/nodes/{FAKE_NODE_ID}/update?version=1", "POST"): post_fake_update_node, (f"{prefix}/{CURRENT_VERSION}/swarm/join", "POST"): post_fake_join_swarm, (f"{prefix}/{CURRENT_VERSION}/networks", "GET"): get_fake_network_list, (f"{prefix}/{CURRENT_VERSION}/networks/create", "POST"): post_fake_network, - ("{1}/{0}/networks/{2}".format(CURRENT_VERSION, prefix, FAKE_NETWORK_ID), "GET"): get_fake_network, - ("{1}/{0}/networks/{2}".format(CURRENT_VERSION, prefix, FAKE_NETWORK_ID), "DELETE"): delete_fake_network, + (f"{prefix}/{CURRENT_VERSION}/networks/{FAKE_NETWORK_ID}", "GET"): get_fake_network, + (f"{prefix}/{CURRENT_VERSION}/networks/{FAKE_NETWORK_ID}", "DELETE"): delete_fake_network, ( - "{1}/{0}/networks/{2}/connect".format(CURRENT_VERSION, prefix, FAKE_NETWORK_ID), + f"{prefix}/{CURRENT_VERSION}/networks/{FAKE_NETWORK_ID}/connect", "POST", ): post_fake_network_connect, ( - "{1}/{0}/networks/{2}/disconnect".format(CURRENT_VERSION, prefix, FAKE_NETWORK_ID), + f"{prefix}/{CURRENT_VERSION}/networks/{FAKE_NETWORK_ID}/disconnect", "POST", ): post_fake_network_disconnect, f"{prefix}/{CURRENT_VERSION}/secrets/create": post_fake_secret, diff --git a/tests/mocks/docker/fake_api_client.py b/tests/mocks/docker/fake_api_client.py index 05b06216a..25df7ab83 100644 --- a/tests/mocks/docker/fake_api_client.py +++ b/tests/mocks/docker/fake_api_client.py @@ -1,15 +1,14 @@ import copy +from unittest import mock import docker from docker.constants import DEFAULT_DOCKER_API_VERSION -from unittest import mock + from . import fake_api class CopyReturnMagicMock(mock.MagicMock): - """ - A MagicMock which deep copies every return value. - """ + """A MagicMock which deep copies every return value.""" def _mock_call(self, *args, **kwargs): ret = super()._mock_call(*args, **kwargs) @@ -19,13 +18,11 @@ def _mock_call(self, *args, **kwargs): def make_fake_api_client(overrides=None): - """ - Returns non-complete fake APIClient. + """Returns non-complete fake APIClient. This returns most of the default cases correctly, but most arguments that change behaviour will not work. """ - if overrides is None: overrides = {} api_client = docker.APIClient(version=DEFAULT_DOCKER_API_VERSION) @@ -57,9 +54,7 @@ def make_fake_api_client(overrides=None): def make_fake_client(overrides=None): - """ - Returns a Client with a fake APIClient. - """ + """Returns a Client with a fake APIClient.""" client = docker.DockerClient(version=DEFAULT_DOCKER_API_VERSION) client.api = make_fake_api_client(overrides) return client diff --git a/tests/mocks/invalid_mock_tool/tool.py b/tests/mocks/invalid_mock_tool/tool.py index 91b2f78f7..fc761cae5 100644 --- a/tests/mocks/invalid_mock_tool/tool.py +++ b/tests/mocks/invalid_mock_tool/tool.py @@ -1,5 +1,6 @@ from attrs import define, field -from schema import Schema, Literal +from schema import Literal, Schema + from griptape.tools import BaseTool from griptape.utils.decorators import activity diff --git a/tests/mocks/mock_audio_input_task.py b/tests/mocks/mock_audio_input_task.py index d6a27d968..95b8c88d0 100644 --- a/tests/mocks/mock_audio_input_task.py +++ b/tests/mocks/mock_audio_input_task.py @@ -1,4 +1,5 @@ from attrs import define + from griptape.artifacts import TextArtifact from griptape.tasks.base_audio_input_task import BaseAudioInputTask diff --git a/tests/mocks/mock_embedding_driver.py b/tests/mocks/mock_embedding_driver.py index e21c56308..46d9bf515 100644 --- a/tests/mocks/mock_embedding_driver.py +++ b/tests/mocks/mock_embedding_driver.py @@ -1,4 +1,7 @@ -from attrs import field, define +from __future__ import annotations + +from attrs import define, field + from griptape.drivers import BaseEmbeddingDriver from tests.mocks.mock_tokenizer import MockTokenizer diff --git a/tests/mocks/mock_event_listener_driver.py b/tests/mocks/mock_event_listener_driver.py index 560fb8733..5833dd1c0 100644 --- a/tests/mocks/mock_event_listener_driver.py +++ b/tests/mocks/mock_event_listener_driver.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from attrs import define from griptape.drivers import BaseEventListenerDriver diff --git a/tests/mocks/mock_failing_prompt_driver.py b/tests/mocks/mock_failing_prompt_driver.py index 0dbeb8fda..18895fdc9 100644 --- a/tests/mocks/mock_failing_prompt_driver.py +++ b/tests/mocks/mock_failing_prompt_driver.py @@ -1,12 +1,17 @@ from __future__ import annotations -from collections.abc import Iterator + +from typing import TYPE_CHECKING + from attrs import define from griptape.artifacts import TextArtifact -from griptape.common import PromptStack, Message, TextMessageContent, DeltaMessage, TextDeltaMessageContent +from griptape.common import DeltaMessage, Message, PromptStack, TextDeltaMessageContent, TextMessageContent from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer +if TYPE_CHECKING: + from collections.abc import Iterator + @define class MockFailingPromptDriver(BasePromptDriver): diff --git a/tests/mocks/mock_image_generation_driver.py b/tests/mocks/mock_image_generation_driver.py index de94771e2..10de11071 100644 --- a/tests/mocks/mock_image_generation_driver.py +++ b/tests/mocks/mock_image_generation_driver.py @@ -1,5 +1,9 @@ +from __future__ import annotations + from typing import Optional + from attrs import define + from griptape.artifacts import ImageArtifact from griptape.drivers.image_generation.base_image_generation_driver import BaseImageGenerationDriver diff --git a/tests/mocks/mock_image_generation_task.py b/tests/mocks/mock_image_generation_task.py index 1c79b42a9..b55c5c995 100644 --- a/tests/mocks/mock_image_generation_task.py +++ b/tests/mocks/mock_image_generation_task.py @@ -13,7 +13,7 @@ def input(self) -> TextArtifact: return self._input @input.setter - def input(self, value: str): + def input(self, value: str) -> None: self._input = TextArtifact(value) def run(self) -> ImageArtifact: diff --git a/tests/mocks/mock_image_query_driver.py b/tests/mocks/mock_image_query_driver.py index d3bec164f..8f8cc888c 100644 --- a/tests/mocks/mock_image_query_driver.py +++ b/tests/mocks/mock_image_query_driver.py @@ -1,8 +1,11 @@ +from __future__ import annotations + from typing import Optional + from attrs import define + from griptape.artifacts import ImageArtifact, TextArtifact from griptape.drivers import BaseImageQueryDriver -from griptape.drivers.image_generation.base_image_generation_driver import BaseImageGenerationDriver @define diff --git a/tests/mocks/mock_multi_text_input_task.py b/tests/mocks/mock_multi_text_input_task.py index 7ab5aedf9..be00bbf65 100644 --- a/tests/mocks/mock_multi_text_input_task.py +++ b/tests/mocks/mock_multi_text_input_task.py @@ -1,4 +1,5 @@ from attrs import define + from griptape.artifacts import TextArtifact from griptape.tasks import BaseMultiTextInputTask diff --git a/tests/mocks/mock_prompt_driver.py b/tests/mocks/mock_prompt_driver.py index 4786b78a6..5a23dd8a2 100644 --- a/tests/mocks/mock_prompt_driver.py +++ b/tests/mocks/mock_prompt_driver.py @@ -1,17 +1,19 @@ from __future__ import annotations -from collections.abc import Iterator -from typing import Callable +from typing import TYPE_CHECKING, Callable from attrs import define, field from griptape.artifacts import TextArtifact -from griptape.common import PromptStack, Message, DeltaMessage, TextMessageContent, TextDeltaMessageContent +from griptape.common import DeltaMessage, Message, PromptStack, TextDeltaMessageContent, TextMessageContent from griptape.drivers import BasePromptDriver -from griptape.tokenizers import BaseTokenizer - from tests.mocks.mock_tokenizer import MockTokenizer +if TYPE_CHECKING: + from collections.abc import Iterator + + from griptape.tokenizers import BaseTokenizer + @define class MockPromptDriver(BasePromptDriver): diff --git a/tests/mocks/mock_serializable.py b/tests/mocks/mock_serializable.py index b02c071aa..b40ae25b4 100644 --- a/tests/mocks/mock_serializable.py +++ b/tests/mocks/mock_serializable.py @@ -1,5 +1,9 @@ -from attrs import define, field +from __future__ import annotations + from typing import Optional + +from attrs import define, field + from griptape.mixins import SerializableMixin @@ -13,4 +17,6 @@ class NestedMockSerializable(SerializableMixin): bar: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": True}) baz: Optional[list[int]] = field(default=None, kw_only=True, metadata={"serializable": True}) secret: Optional[str] = field(default=None, kw_only=True, metadata={"serializable": False}) - nested: Optional[NestedMockSerializable] = field(default=None, kw_only=True, metadata={"serializable": True}) + nested: Optional[MockSerializable.NestedMockSerializable] = field( + default=None, kw_only=True, metadata={"serializable": True} + ) diff --git a/tests/mocks/mock_structure_config.py b/tests/mocks/mock_structure_config.py index 8309f541b..3f95288f4 100644 --- a/tests/mocks/mock_structure_config.py +++ b/tests/mocks/mock_structure_config.py @@ -1,9 +1,10 @@ -from attrs import define, field, Factory +from attrs import Factory, define, field + from griptape.config import StructureConfig +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_image_generation_driver import MockImageGenerationDriver from tests.mocks.mock_image_query_driver import MockImageQueryDriver from tests.mocks.mock_prompt_driver import MockPromptDriver -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @define diff --git a/tests/mocks/mock_task.py b/tests/mocks/mock_task.py index 42595f6eb..81aa03713 100644 --- a/tests/mocks/mock_task.py +++ b/tests/mocks/mock_task.py @@ -1,5 +1,6 @@ from attrs import define, field -from griptape.artifacts import TextArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, TextArtifact from griptape.tasks import BaseTask diff --git a/tests/mocks/mock_text_input_task.py b/tests/mocks/mock_text_input_task.py index 930c77e74..f1439bd42 100644 --- a/tests/mocks/mock_text_input_task.py +++ b/tests/mocks/mock_text_input_task.py @@ -1,4 +1,5 @@ from attrs import define + from griptape.artifacts import TextArtifact from griptape.tasks import BaseTextInputTask diff --git a/tests/mocks/mock_tokenizer.py b/tests/mocks/mock_tokenizer.py index eff103e99..b16332ce0 100644 --- a/tests/mocks/mock_tokenizer.py +++ b/tests/mocks/mock_tokenizer.py @@ -1,5 +1,7 @@ from __future__ import annotations + from attrs import define + from griptape.tokenizers import BaseTokenizer diff --git a/tests/mocks/mock_tool/tool.py b/tests/mocks/mock_tool/tool.py index e79023a6e..7d09f391e 100644 --- a/tests/mocks/mock_tool/tool.py +++ b/tests/mocks/mock_tool/tool.py @@ -1,6 +1,7 @@ from attrs import define, field -from schema import Schema, Literal -from griptape.artifacts import TextArtifact, ErrorArtifact, BaseArtifact, ListArtifact +from schema import Literal, Schema + +from griptape.artifacts import BaseArtifact, ErrorArtifact, ListArtifact, TextArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity @@ -49,7 +50,7 @@ def test_str_output(self, value: dict) -> str: @activity(config={"description": "test description"}) def test_no_schema(self, value: dict) -> str: - return f"no schema" + return "no schema" @activity(config={"description": "test description"}) def test_list_output(self, value: dict) -> ListArtifact: diff --git a/tests/unit/artifacts/test_action_artifact.py b/tests/unit/artifacts/test_action_artifact.py index e415bbdaf..2530ed8c3 100644 --- a/tests/unit/artifacts/test_action_artifact.py +++ b/tests/unit/artifacts/test_action_artifact.py @@ -1,7 +1,9 @@ import json + import pytest -from griptape.common import ToolAction + from griptape.artifacts import ActionArtifact, BaseArtifact +from griptape.common import ToolAction class TestActionArtifact: @@ -11,7 +13,7 @@ def action(self) -> ToolAction: def test___add__(self, action): with pytest.raises(NotImplementedError): - result = ActionArtifact(action) + ActionArtifact(action) + ActionArtifact(action) + ActionArtifact(action) def test_to_text(self, action): assert ActionArtifact(action).to_text() == json.dumps(action.to_dict()) diff --git a/tests/unit/artifacts/test_audio_artifact.py b/tests/unit/artifacts/test_audio_artifact.py index 93ea816e4..6d44c05b3 100644 --- a/tests/unit/artifacts/test_audio_artifact.py +++ b/tests/unit/artifacts/test_audio_artifact.py @@ -1,9 +1,10 @@ import pytest + from griptape.artifacts import AudioArtifact, BaseArtifact class TestAudioArtifact: - @pytest.fixture + @pytest.fixture() def audio_artifact(self): return AudioArtifact(value=b"some binary audio data", format="pcm", model="provider/model", prompt="two words") diff --git a/tests/unit/artifacts/test_base_artifact.py b/tests/unit/artifacts/test_base_artifact.py index a7d7acaaf..6cf8f4466 100644 --- a/tests/unit/artifacts/test_base_artifact.py +++ b/tests/unit/artifacts/test_base_artifact.py @@ -1,12 +1,13 @@ import pytest + from griptape.artifacts import ( BaseArtifact, - TextArtifact, + BlobArtifact, ErrorArtifact, + ImageArtifact, InfoArtifact, ListArtifact, - BlobArtifact, - ImageArtifact, + TextArtifact, ) diff --git a/tests/unit/artifacts/test_base_media_artifact.py b/tests/unit/artifacts/test_base_media_artifact.py index 2829a1e2f..c85d070fe 100644 --- a/tests/unit/artifacts/test_base_media_artifact.py +++ b/tests/unit/artifacts/test_base_media_artifact.py @@ -1,5 +1,4 @@ import pytest - from attrs import define from griptape.artifacts import MediaArtifact @@ -10,7 +9,7 @@ class TestMediaArtifact: class ImaginaryMediaArtifact(MediaArtifact): media_type: str = "imagination" - @pytest.fixture + @pytest.fixture() def media_artifact(self): return self.ImaginaryMediaArtifact(value=b"some binary dream data", format="dream") diff --git a/tests/unit/artifacts/test_blob_artifact.py b/tests/unit/artifacts/test_blob_artifact.py index 08844d241..a50a673f4 100644 --- a/tests/unit/artifacts/test_blob_artifact.py +++ b/tests/unit/artifacts/test_blob_artifact.py @@ -1,6 +1,8 @@ import base64 + import pytest -from griptape.artifacts import BlobArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, BlobArtifact class TestBlobArtifact: diff --git a/tests/unit/artifacts/test_boolean_artifact.py b/tests/unit/artifacts/test_boolean_artifact.py index bcad67673..57bbf1662 100644 --- a/tests/unit/artifacts/test_boolean_artifact.py +++ b/tests/unit/artifacts/test_boolean_artifact.py @@ -1,4 +1,6 @@ +# ruff: noqa: FBT003 import pytest + from griptape.artifacts import BooleanArtifact @@ -13,14 +15,14 @@ def test_parse_bool(self): BooleanArtifact.parse_bool("foo") with pytest.raises(ValueError): - BooleanArtifact.parse_bool(None) + BooleanArtifact.parse_bool(None) # pyright: ignore[reportArgumentType] assert BooleanArtifact.parse_bool(True).value is True assert BooleanArtifact.parse_bool(False).value is False def test_add(self): with pytest.raises(ValueError): - BooleanArtifact(True) + BooleanArtifact(True) + BooleanArtifact(True) + BooleanArtifact(True) # pyright: ignore[reportUnusedExpression] def test_value_type_conversion(self): assert BooleanArtifact(1).value is True @@ -31,5 +33,5 @@ def test_value_type_conversion(self): assert BooleanArtifact("false").value is True assert BooleanArtifact([1]).value is True assert BooleanArtifact([]).value is False - assert BooleanArtifact(False) == False - assert BooleanArtifact(True) == True + assert BooleanArtifact(False).value is False + assert BooleanArtifact(True).value is True diff --git a/tests/unit/artifacts/test_image_artifact.py b/tests/unit/artifacts/test_image_artifact.py index 687397260..a722ebd91 100644 --- a/tests/unit/artifacts/test_image_artifact.py +++ b/tests/unit/artifacts/test_image_artifact.py @@ -1,9 +1,10 @@ import pytest -from griptape.artifacts import ImageArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, ImageArtifact class TestImageArtifact: - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact( value=b"some binary png image data", diff --git a/tests/unit/artifacts/test_list_artifact.py b/tests/unit/artifacts/test_list_artifact.py index 044ca8ed5..06d234645 100644 --- a/tests/unit/artifacts/test_list_artifact.py +++ b/tests/unit/artifacts/test_list_artifact.py @@ -1,5 +1,6 @@ import pytest -from griptape.artifacts import ListArtifact, TextArtifact, BlobArtifact, CsvRowArtifact + +from griptape.artifacts import BlobArtifact, CsvRowArtifact, ListArtifact, TextArtifact class TestListArtifact: diff --git a/tests/unit/artifacts/test_text_artifact.py b/tests/unit/artifacts/test_text_artifact.py index 6ea2c6697..067da0912 100644 --- a/tests/unit/artifacts/test_text_artifact.py +++ b/tests/unit/artifacts/test_text_artifact.py @@ -1,6 +1,8 @@ import json + import pytest -from griptape.artifacts import TextArtifact, BaseArtifact + +from griptape.artifacts import BaseArtifact, TextArtifact from griptape.tokenizers import OpenAiTokenizer from tests.mocks.mock_embedding_driver import MockEmbeddingDriver diff --git a/tests/unit/chunkers/test_markdown_chunker.py b/tests/unit/chunkers/test_markdown_chunker.py index 08709c092..30db64611 100644 --- a/tests/unit/chunkers/test_markdown_chunker.py +++ b/tests/unit/chunkers/test_markdown_chunker.py @@ -1,4 +1,5 @@ import pytest + from griptape.chunkers import MarkdownChunker from tests.unit.chunkers.test_text_chunker import gen_paragraph @@ -6,7 +7,7 @@ class TestTextChunker: - @pytest.fixture + @pytest.fixture() def chunker(self): return MarkdownChunker(max_tokens=MAX_TOKENS) diff --git a/tests/unit/chunkers/test_pdf_chunker.py b/tests/unit/chunkers/test_pdf_chunker.py index 605c2f6e6..dc072ca36 100644 --- a/tests/unit/chunkers/test_pdf_chunker.py +++ b/tests/unit/chunkers/test_pdf_chunker.py @@ -1,13 +1,15 @@ import os + import pytest from pypdf import PdfReader + from griptape.chunkers import PdfChunker MAX_TOKENS = 500 class TestPdfChunker: - @pytest.fixture + @pytest.fixture() def chunker(self): return PdfChunker(max_tokens=MAX_TOKENS) diff --git a/tests/unit/chunkers/test_text_chunker.py b/tests/unit/chunkers/test_text_chunker.py index 243b287e1..d9d01f16c 100644 --- a/tests/unit/chunkers/test_text_chunker.py +++ b/tests/unit/chunkers/test_text_chunker.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts import TextArtifact from griptape.chunkers import TextChunker from tests.unit.chunkers.utils import gen_paragraph @@ -7,7 +8,7 @@ class TestTextChunker: - @pytest.fixture + @pytest.fixture() def chunker(self): return TextChunker(max_tokens=MAX_TOKENS) diff --git a/tests/unit/chunkers/utils.py b/tests/unit/chunkers/utils.py index 80335e978..b9e7b8539 100644 --- a/tests/unit/chunkers/utils.py +++ b/tests/unit/chunkers/utils.py @@ -5,7 +5,9 @@ def gen_paragraph(max_tokens: int, tokenizer: BaseTokenizer, sentence_separator: all_text = "" word = "foo" index = 0 - add_word = lambda base, w, i: sentence_separator.join([base, f"{w}-{i}"]) + + def add_word(base, w, i): + return sentence_separator.join([base, f"{w}-{i}"]) while max_tokens >= tokenizer.count_tokens(add_word(all_text, word, index)): all_text = f"{word}-{index}" if all_text == "" else add_word(all_text, word, index) diff --git a/tests/unit/common/contents/test_action_call_message_content.py b/tests/unit/common/contents/test_action_call_message_content.py index 2e2e69d27..d6c3f438f 100644 --- a/tests/unit/common/contents/test_action_call_message_content.py +++ b/tests/unit/common/contents/test_action_call_message_content.py @@ -1,6 +1,7 @@ import pytest + from griptape.artifacts.action_artifact import ActionArtifact -from griptape.common import ActionCallMessageContent, ActionCallDeltaMessageContent, ToolAction +from griptape.common import ActionCallDeltaMessageContent, ActionCallMessageContent, ToolAction class TestActionCallMessageContent: diff --git a/tests/unit/common/contents/test_action_result_message_content.py b/tests/unit/common/contents/test_action_result_message_content.py index b1bcc356d..c5eed60d9 100644 --- a/tests/unit/common/contents/test_action_result_message_content.py +++ b/tests/unit/common/contents/test_action_result_message_content.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts.text_artifact import TextArtifact from griptape.common import ActionResultMessageContent, ToolAction diff --git a/tests/unit/common/contents/test_image_message_content.py b/tests/unit/common/contents/test_image_message_content.py index b6c1b4c4f..ff8dbe59d 100644 --- a/tests/unit/common/contents/test_image_message_content.py +++ b/tests/unit/common/contents/test_image_message_content.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts.image_artifact import ImageArtifact from griptape.common import ImageMessageContent diff --git a/tests/unit/common/contents/test_text_message_content.py b/tests/unit/common/contents/test_text_message_content.py index 01a3c0fd4..eab9eb718 100644 --- a/tests/unit/common/contents/test_text_message_content.py +++ b/tests/unit/common/contents/test_text_message_content.py @@ -1,5 +1,5 @@ from griptape.artifacts.text_artifact import TextArtifact -from griptape.common import TextMessageContent, TextDeltaMessageContent +from griptape.common import TextDeltaMessageContent, TextMessageContent class TestTextMessageContent: diff --git a/tests/unit/common/test_action.py b/tests/unit/common/test_action.py index db5284839..8fcf09a57 100644 --- a/tests/unit/common/test_action.py +++ b/tests/unit/common/test_action.py @@ -1,5 +1,7 @@ -import pytest import json + +import pytest + from griptape.common import ToolAction diff --git a/tests/unit/common/test_prompt_stack.py b/tests/unit/common/test_prompt_stack.py index 83a16e140..e69fe710d 100644 --- a/tests/unit/common/test_prompt_stack.py +++ b/tests/unit/common/test_prompt_stack.py @@ -1,13 +1,18 @@ import pytest -from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact, ActionArtifact -from griptape.common import ImageMessageContent, PromptStack, TextMessageContent -from griptape.common import ActionCallMessageContent -from griptape.common import ActionResultMessageContent, ToolAction +from griptape.artifacts import ActionArtifact, ImageArtifact, ListArtifact, TextArtifact +from griptape.common import ( + ActionCallMessageContent, + ActionResultMessageContent, + ImageMessageContent, + PromptStack, + TextMessageContent, + ToolAction, +) class TestPromptStack: - @pytest.fixture + @pytest.fixture() def prompt_stack(self): return PromptStack() diff --git a/tests/unit/config/test_amazon_bedrock_structure_config.py b/tests/unit/config/test_amazon_bedrock_structure_config.py index 824e6ce11..afe9b3720 100644 --- a/tests/unit/config/test_amazon_bedrock_structure_config.py +++ b/tests/unit/config/test_amazon_bedrock_structure_config.py @@ -1,20 +1,21 @@ import boto3 -from pytest import fixture +import pytest + from griptape.config import AmazonBedrockStructureConfig from tests.utils.aws import mock_aws_credentials class TestAmazonBedrockStructureConfig: - @fixture(autouse=True) - def run_before_and_after_tests(self): + @pytest.fixture(autouse=True) + def _run_before_and_after_tests(self): mock_aws_credentials() - @fixture + @pytest.fixture() def config(self): mock_aws_credentials() return AmazonBedrockStructureConfig() - @fixture + @pytest.fixture() def config_with_values(self): return AmazonBedrockStructureConfig( session=boto3.Session( diff --git a/tests/unit/config/test_anthropic_structure_config.py b/tests/unit/config/test_anthropic_structure_config.py index b41309a83..05519fa5e 100644 --- a/tests/unit/config/test_anthropic_structure_config.py +++ b/tests/unit/config/test_anthropic_structure_config.py @@ -1,14 +1,15 @@ -from pytest import fixture +import pytest + from griptape.config import AnthropicStructureConfig class TestAnthropicStructureConfig: - @fixture(autouse=True) - def mock_anthropic(self, mocker): + @pytest.fixture(autouse=True) + def _mock_anthropic(self, mocker): mocker.patch("anthropic.Anthropic") mocker.patch("voyageai.Client") - @fixture + @pytest.fixture() def config(self): return AnthropicStructureConfig() diff --git a/tests/unit/config/test_azure_openai_structure_config.py b/tests/unit/config/test_azure_openai_structure_config.py index 58d557fb9..dcdc3a1dc 100644 --- a/tests/unit/config/test_azure_openai_structure_config.py +++ b/tests/unit/config/test_azure_openai_structure_config.py @@ -1,13 +1,14 @@ -from pytest import fixture +import pytest + from griptape.config import AzureOpenAiStructureConfig class TestAzureOpenAiStructureConfig: - @fixture(autouse=True) + @pytest.fixture(autouse=True) def mock_openai(self, mocker): return mocker.patch("openai.AzureOpenAI") - @fixture + @pytest.fixture() def config(self): return AzureOpenAiStructureConfig( azure_endpoint="http://localhost:8080", diff --git a/tests/unit/config/test_cohere_structure_config.py b/tests/unit/config/test_cohere_structure_config.py index 44ed3e4d8..113a589ec 100644 --- a/tests/unit/config/test_cohere_structure_config.py +++ b/tests/unit/config/test_cohere_structure_config.py @@ -1,9 +1,10 @@ -from pytest import fixture +import pytest + from griptape.config import CohereStructureConfig class TestCohereStructureConfig: - @fixture + @pytest.fixture() def config(self): return CohereStructureConfig(api_key="api_key") diff --git a/tests/unit/config/test_google_structure_config.py b/tests/unit/config/test_google_structure_config.py index 469493e2c..e193cc983 100644 --- a/tests/unit/config/test_google_structure_config.py +++ b/tests/unit/config/test_google_structure_config.py @@ -1,13 +1,14 @@ -from pytest import fixture +import pytest + from griptape.config import GoogleStructureConfig class TestGoogleStructureConfig: - @fixture(autouse=True) + @pytest.fixture(autouse=True) def mock_openai(self, mocker): return mocker.patch("google.generativeai.GenerativeModel") - @fixture + @pytest.fixture() def config(self): return GoogleStructureConfig() diff --git a/tests/unit/config/test_openai_structure_config.py b/tests/unit/config/test_openai_structure_config.py index 19321006f..8969e0ad0 100644 --- a/tests/unit/config/test_openai_structure_config.py +++ b/tests/unit/config/test_openai_structure_config.py @@ -1,13 +1,14 @@ -from pytest import fixture +import pytest + from griptape.config import OpenAiStructureConfig class TestOpenAiStructureConfig: - @fixture(autouse=True) + @pytest.fixture(autouse=True) def mock_openai(self, mocker): return mocker.patch("openai.OpenAI") - @fixture + @pytest.fixture() def config(self): return OpenAiStructureConfig() diff --git a/tests/unit/config/test_structure_config.py b/tests/unit/config/test_structure_config.py index 27aaf81c4..96a68628f 100644 --- a/tests/unit/config/test_structure_config.py +++ b/tests/unit/config/test_structure_config.py @@ -1,9 +1,10 @@ -from pytest import fixture +import pytest + from griptape.config import StructureConfig class TestStructureConfig: - @fixture + @pytest.fixture() def config(self): return StructureConfig() diff --git a/tests/unit/drivers/embedding/test_amazon_bedrock_cohere_embedding_driver.py b/tests/unit/drivers/embedding/test_amazon_bedrock_cohere_embedding_driver.py index ba8edad90..5644227c9 100644 --- a/tests/unit/drivers/embedding/test_amazon_bedrock_cohere_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_amazon_bedrock_cohere_embedding_driver.py @@ -1,11 +1,13 @@ -import pytest from unittest import mock + +import pytest + from griptape.drivers import AmazonBedrockCohereEmbeddingDriver class TestAmazonBedrockCohereEmbeddingDriver: @pytest.fixture(autouse=True) - def mock_session(self, mocker): + def _mock_session(self, mocker): fake_embeddings = '{"embeddings": [[0, 1, 0]] }' mock_session_class = mocker.patch("boto3.Session") diff --git a/tests/unit/drivers/embedding/test_amazon_bedrock_titan_embedding_driver.py b/tests/unit/drivers/embedding/test_amazon_bedrock_titan_embedding_driver.py index df4455c24..4470cf62b 100644 --- a/tests/unit/drivers/embedding/test_amazon_bedrock_titan_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_amazon_bedrock_titan_embedding_driver.py @@ -1,11 +1,13 @@ -import pytest from unittest import mock + +import pytest + from griptape.drivers import AmazonBedrockTitanEmbeddingDriver class TestAmazonBedrockTitanEmbeddingDriver: @pytest.fixture(autouse=True) - def mock_session(self, mocker): + def _mock_session(self, mocker): fake_embeddings = '{"embedding": [0, 1, 0]}' mock_session_class = mocker.patch("boto3.Session") diff --git a/tests/unit/drivers/embedding/test_azure_openai_embedding_driver.py b/tests/unit/drivers/embedding/test_azure_openai_embedding_driver.py index d2c20c043..7f604434b 100644 --- a/tests/unit/drivers/embedding/test_azure_openai_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_azure_openai_embedding_driver.py @@ -1,5 +1,7 @@ from unittest.mock import Mock + import pytest + from griptape.drivers import AzureOpenAiEmbeddingDriver @@ -17,7 +19,7 @@ def mock_openai(self, mocker): return mock_chat_create - @pytest.fixture + @pytest.fixture() def driver(self): return AzureOpenAiEmbeddingDriver(azure_endpoint="foobar", model="gpt-4", azure_deployment="foobar") diff --git a/tests/unit/drivers/embedding/test_base_embedding_driver.py b/tests/unit/drivers/embedding/test_base_embedding_driver.py index 24b07778d..4413468b6 100644 --- a/tests/unit/drivers/embedding/test_base_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_base_embedding_driver.py @@ -1,11 +1,13 @@ +from unittest.mock import patch + import pytest + from griptape.artifacts import TextArtifact from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from unittest.mock import patch class TestBaseEmbeddingDriver: - @pytest.fixture + @pytest.fixture() def driver(self): return MockEmbeddingDriver() diff --git a/tests/unit/drivers/embedding/test_cohere_embedding_driver.py b/tests/unit/drivers/embedding/test_cohere_embedding_driver.py index af6a5576d..024e0e74c 100644 --- a/tests/unit/drivers/embedding/test_cohere_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_cohere_embedding_driver.py @@ -1,5 +1,7 @@ from unittest.mock import Mock + import pytest + from griptape.drivers import CohereEmbeddingDriver diff --git a/tests/unit/drivers/embedding/test_dummy_embedding_driver.py b/tests/unit/drivers/embedding/test_dummy_embedding_driver.py index 35f81bf77..af56ce6ac 100644 --- a/tests/unit/drivers/embedding/test_dummy_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_dummy_embedding_driver.py @@ -1,11 +1,11 @@ -from griptape.drivers import DummyEmbeddingDriver import pytest +from griptape.drivers import DummyEmbeddingDriver from griptape.exceptions import DummyException class TestDummyEmbeddingDriver: - @pytest.fixture + @pytest.fixture() def embedding_driver(self): return DummyEmbeddingDriver() diff --git a/tests/unit/drivers/embedding/test_google_embedding_driver.py b/tests/unit/drivers/embedding/test_google_embedding_driver.py index 324b95ddb..9e756491e 100644 --- a/tests/unit/drivers/embedding/test_google_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_google_embedding_driver.py @@ -1,5 +1,7 @@ from unittest.mock import MagicMock + import pytest + from griptape.drivers import GoogleEmbeddingDriver diff --git a/tests/unit/drivers/embedding/test_ollama_embedding_driver.py b/tests/unit/drivers/embedding/test_ollama_embedding_driver.py index 3886ab874..6dda23930 100644 --- a/tests/unit/drivers/embedding/test_ollama_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_ollama_embedding_driver.py @@ -1,4 +1,5 @@ import pytest + from griptape.drivers import OllamaEmbeddingDriver diff --git a/tests/unit/drivers/embedding/test_openai_embedding_driver.py b/tests/unit/drivers/embedding/test_openai_embedding_driver.py index fd30dd30f..78879345a 100644 --- a/tests/unit/drivers/embedding/test_openai_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_openai_embedding_driver.py @@ -1,5 +1,7 @@ -from unittest.mock import Mock, MagicMock +from unittest.mock import Mock + import pytest + from griptape.drivers import OpenAiEmbeddingDriver from griptape.tokenizers import OpenAiTokenizer diff --git a/tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py b/tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py index 268b47c54..09ec8ec87 100644 --- a/tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_sagemaker_jumpstart_embedding_driver.py @@ -1,5 +1,7 @@ -import pytest from unittest import mock + +import pytest + from griptape.drivers import AmazonSageMakerJumpstartEmbeddingDriver from griptape.tokenizers.openai_tokenizer import OpenAiTokenizer @@ -41,19 +43,17 @@ def test_try_embed_chunk(self, mock_client): ).try_embed_chunk("foobar") == [0, 2, 0] mock_client.get().read.return_value = b'{"embedding": []}' - with pytest.raises(ValueError) as e: + with pytest.raises(ValueError, match="model response is empty"): assert AmazonSageMakerJumpstartEmbeddingDriver( endpoint="test-endpoint", model="test-model", tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), ).try_embed_chunk("foobar") == [0, 2, 0] - assert str(e) == "model response is empty" mock_client.get().read.return_value = b"{}" - with pytest.raises(ValueError) as e: + with pytest.raises(ValueError, match="invalid response from model"): assert AmazonSageMakerJumpstartEmbeddingDriver( endpoint="test-endpoint", model="test-model", tokenizer=OpenAiTokenizer(model=OpenAiTokenizer.DEFAULT_OPENAI_GPT_3_CHAT_MODEL), ).try_embed_chunk("foobar") == [0, 2, 0] - assert str(e) == "invalid response from model" diff --git a/tests/unit/drivers/embedding/test_voyageai_embedding_driver.py b/tests/unit/drivers/embedding/test_voyageai_embedding_driver.py index 69db0213c..5371f8db0 100644 --- a/tests/unit/drivers/embedding/test_voyageai_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_voyageai_embedding_driver.py @@ -1,5 +1,7 @@ -import pytest from unittest.mock import Mock + +import pytest + from griptape.drivers import VoyageAiEmbeddingDriver diff --git a/tests/unit/drivers/event_listener/test_amazon_sqs_event_listener_driver.py b/tests/unit/drivers/event_listener/test_amazon_sqs_event_listener_driver.py index 706831d67..10ef0354c 100644 --- a/tests/unit/drivers/event_listener/test_amazon_sqs_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_amazon_sqs_event_listener_driver.py @@ -1,17 +1,18 @@ -from pytest import fixture -from moto import mock_sqs import boto3 -from tests.mocks.mock_event import MockEvent +import pytest +from moto import mock_sqs + from griptape.drivers.event_listener.amazon_sqs_event_listener_driver import AmazonSqsEventListenerDriver +from tests.mocks.mock_event import MockEvent from tests.utils.aws import mock_aws_credentials class TestAmazonSqsEventListenerDriver: - @fixture() - def run_before_and_after_tests(self): + @pytest.fixture() + def _run_before_and_after_tests(self): mock_aws_credentials() - @fixture() + @pytest.fixture() def driver(self): mock = mock_sqs() mock.start() diff --git a/tests/unit/drivers/event_listener/test_aws_iot_event_listener_driver.py b/tests/unit/drivers/event_listener/test_aws_iot_event_listener_driver.py index 9a5fe9ec0..b597a5332 100644 --- a/tests/unit/drivers/event_listener/test_aws_iot_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_aws_iot_event_listener_driver.py @@ -1,18 +1,19 @@ -from pytest import fixture -from moto import mock_iotdata import boto3 -from tests.mocks.mock_event import MockEvent +import pytest +from moto import mock_iotdata + from griptape.drivers.event_listener.aws_iot_core_event_listener_driver import AwsIotCoreEventListenerDriver +from tests.mocks.mock_event import MockEvent from tests.utils.aws import mock_aws_credentials @mock_iotdata class TestAwsIotCoreEventListenerDriver: - @fixture(autouse=True) - def run_before_and_after_tests(self): + @pytest.fixture(autouse=True) + def _run_before_and_after_tests(self): mock_aws_credentials() - @fixture() + @pytest.fixture() def driver(self): return AwsIotCoreEventListenerDriver( iot_endpoint="foo bar", topic="fizz buzz", session=boto3.Session(region_name="us-east-1") diff --git a/tests/unit/drivers/event_listener/test_base_event_listener_driver.py b/tests/unit/drivers/event_listener/test_base_event_listener_driver.py index 383c0be89..04cfef34b 100644 --- a/tests/unit/drivers/event_listener/test_base_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_base_event_listener_driver.py @@ -1,4 +1,5 @@ from unittest.mock import MagicMock + from tests.mocks.mock_event import MockEvent from tests.mocks.mock_event_listener_driver import MockEventListenerDriver diff --git a/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py b/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py index d27f09ec8..b651841ca 100644 --- a/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py @@ -2,14 +2,13 @@ from unittest.mock import Mock import pytest -from pytest import fixture from griptape.drivers.event_listener.griptape_cloud_event_listener_driver import GriptapeCloudEventListenerDriver from tests.mocks.mock_event import MockEvent class TestGriptapeCloudEventListenerDriver: - @fixture(autouse=True) + @pytest.fixture(autouse=True) def mock_post(self, mocker): data = {"data": {"id": "test"}} @@ -18,7 +17,7 @@ def mock_post(self, mocker): return mock_post - @fixture() + @pytest.fixture() def driver(self): os.environ["GT_CLOUD_BASE_URL"] = "https://cloud123.griptape.ai" diff --git a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py index 6f0636b5c..50856c0da 100644 --- a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py @@ -1,11 +1,13 @@ -from pytest import fixture -from tests.mocks.mock_event import MockEvent -from griptape.drivers import PusherEventListenerDriver from unittest.mock import Mock +import pytest + +from griptape.drivers import PusherEventListenerDriver +from tests.mocks.mock_event import MockEvent + class TestPusherEventListenerDriver: - @fixture(autouse=True) + @pytest.fixture(autouse=True) def mock_post(self, mocker): mock_pusher_client = mocker.patch("pusher.Pusher") mock_pusher_client.return_value.trigger.return_value = Mock() @@ -13,7 +15,7 @@ def mock_post(self, mocker): return mock_pusher_client - @fixture() + @pytest.fixture() def driver(self): return PusherEventListenerDriver( app_id="test-app-id", diff --git a/tests/unit/drivers/event_listener/test_webhook_event_listener_driver.py b/tests/unit/drivers/event_listener/test_webhook_event_listener_driver.py index 50021cbe3..f6de0d20f 100644 --- a/tests/unit/drivers/event_listener/test_webhook_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_webhook_event_listener_driver.py @@ -1,11 +1,13 @@ from unittest.mock import Mock -from pytest import fixture -from tests.mocks.mock_event import MockEvent + +import pytest + from griptape.drivers.event_listener.webhook_event_listener_driver import WebhookEventListenerDriver +from tests.mocks.mock_event import MockEvent class TestWebhookEventListenerDriver: - @fixture(autouse=True) + @pytest.fixture(autouse=True) def mock_post(self, mocker): mock_post = mocker.patch("requests.post") mock_post.return_value = Mock(status_code=201) diff --git a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py index 8d1693ade..cad76a7d6 100644 --- a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py @@ -1,9 +1,11 @@ import os import tempfile + import boto3 import pytest from moto import mock_s3 -from griptape.artifacts import ErrorArtifact, ListArtifact, InfoArtifact, TextArtifact + +from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.drivers import AmazonS3FileManagerDriver from griptape.loaders import TextLoader from tests.utils.aws import mock_aws_credentials @@ -11,35 +13,35 @@ class TestAmazonS3FileManagerDriver: @pytest.fixture(autouse=True) - def set_aws_credentials(self): + def _set_aws_credentials(self): mock_aws_credentials() - @pytest.fixture + @pytest.fixture() def session(self): mock = mock_s3() mock.start() yield boto3.Session(region_name="us-east-1") mock.stop() - @pytest.fixture + @pytest.fixture() def s3_client(self, session): - yield session.client("s3") + return session.client("s3") @pytest.fixture(autouse=True) def bucket(self, s3_client): bucket = "test-bucket" s3_client.create_bucket(Bucket=bucket) - def write_file(path: str, content: bytes): + def write_file(path: str, content: bytes) -> None: s3_client.put_object(Bucket=bucket, Key=path, Body=content) - def mkdir(path: str): + def mkdir(path: str) -> None: # S3-style empty directories, such as is created via the `Create Folder` button # in the AWS S3 console (essentially, an empty file with a trailing slash). s3_dir_key = path.rstrip("/") + "/" s3_client.put_object(Bucket=bucket, Key=s3_dir_key) - def copy_test_resource(resource_path: str): + def copy_test_resource(resource_path: str) -> None: file_dir = os.path.dirname(__file__) full_path = os.path.join(file_dir, "../../../resources", resource_path) full_path = os.path.normpath(full_path) @@ -58,18 +60,18 @@ def copy_test_resource(resource_path: str): mkdir("foo/bar-empty") mkdir("foo/bar/baz-empty") - yield bucket + return bucket - @pytest.fixture + @pytest.fixture() def driver(self, session, bucket): return AmazonS3FileManagerDriver(session=session, bucket=bucket) - @pytest.fixture + @pytest.fixture() def temp_dir(self): with tempfile.TemporaryDirectory() as temp_dir: yield temp_dir - @pytest.fixture + @pytest.fixture() def get_s3_value(self, s3_client, bucket): def _get_s3_value(key): return s3_client.get_object(Bucket=bucket, Key=key)["Body"].read().decode() @@ -82,7 +84,7 @@ def test_validate_workdir(self, workdir, session, bucket): AmazonS3FileManagerDriver(session=session, bucket=bucket, workdir=workdir) @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # Valid non-empty directories (without trailing slash) ("/", "", ["foo", "foo.txt", "foo-empty", "resources"]), @@ -130,7 +132,7 @@ def test_list_files(self, workdir, path, expected, driver): assert set(filter(None, artifact.value.split("\n"))) == set(expected) @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # non-existent paths ("/", "bar", "Path not found"), @@ -158,7 +160,7 @@ def test_load_file(self, driver): assert len(artifact.value) == 4 @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # non-existent files or directories ("/", "bitcoin.pdf", "Path not found"), @@ -201,7 +203,7 @@ def test_load_file_with_encoding_failure(self, session, bucket): assert isinstance(artifact, ErrorArtifact) @pytest.mark.parametrize( - "workdir,path,content", + ("workdir", "path", "content"), [ # non-existent files ("/", "resources/foo.txt", "one"), @@ -226,7 +228,7 @@ def test_save_file(self, workdir, path, content, driver, get_s3_value): assert get_s3_value(expected_s3_key) == content_str @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # non-existent directories ("/", "bar/", "Path is a directory"), @@ -248,11 +250,6 @@ def test_save_file_failure(self, workdir, path, expected, temp_dir, driver, s3_c artifact = driver.save_file(path, "foobar") - # loop over the files in the bucket and print them - response = s3_client.list_objects_v2(Bucket=bucket) - for obj in response.get("Contents", []): - print(obj.get("Key")) - assert isinstance(artifact, ErrorArtifact) assert artifact.value == expected diff --git a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py index b3f4ec561..ec9963b49 100644 --- a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py @@ -1,28 +1,30 @@ import os -from pathlib import Path import tempfile +from pathlib import Path + import pytest -from griptape.artifacts import ErrorArtifact, ListArtifact, InfoArtifact, TextArtifact + +from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.drivers import LocalFileManagerDriver from griptape.loaders.text_loader import TextLoader class TestLocalFileManagerDriver: - @pytest.fixture + @pytest.fixture() def temp_dir(self): with tempfile.TemporaryDirectory() as temp_dir: - def write_file(path: str, content: bytes): + def write_file(path: str, content: bytes) -> None: full_path = os.path.join(temp_dir, path) os.makedirs(os.path.dirname(full_path), exist_ok=True) with open(full_path, "wb") as f: f.write(content) - def mkdir(path: str): + def mkdir(path: str) -> None: full_path = os.path.join(temp_dir, path) os.makedirs(full_path, exist_ok=True) - def copy_test_resources(resource_path: str): + def copy_test_resources(resource_path: str) -> None: file_dir = os.path.dirname(__file__) full_path = os.path.join(file_dir, "../../../resources", resource_path) full_path = os.path.normpath(full_path) @@ -46,7 +48,7 @@ def copy_test_resources(resource_path: str): yield temp_dir - @pytest.fixture + @pytest.fixture() def driver(self, temp_dir): return LocalFileManagerDriver(workdir=temp_dir) @@ -55,7 +57,7 @@ def test_validate_workdir(self): LocalFileManagerDriver(workdir="foo") @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # Valid non-empty directories (without trailing slash) ("/", "", ["foo", "foo.txt", "foo-empty", "resources"]), @@ -104,7 +106,7 @@ def test_list_files(self, workdir, path, expected, temp_dir, driver): assert set(filter(None, artifact.value.split("\n"))) == set(expected) @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # non-existent paths ("/", "bar", "Path not found"), @@ -133,7 +135,7 @@ def test_load_file(self, driver: LocalFileManagerDriver): assert len(artifact.value) == 4 @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # # non-existent files or directories ("/", "bitcoin.pdf", "Path not found"), @@ -177,7 +179,7 @@ def test_load_file_with_encoding_failure(self): assert isinstance(artifact, ErrorArtifact) @pytest.mark.parametrize( - "workdir,path,content", + ("workdir", "path", "content"), [ # non-existent files ("/", "resources/foo.txt", "one"), @@ -202,7 +204,7 @@ def test_save_file(self, workdir, path, content, temp_dir, driver): assert Path(driver.workdir, path).read_text() == content_bytes @pytest.mark.parametrize( - "workdir,path,expected", + ("workdir", "path", "expected"), [ # non-existent directories ("/", "bar/", "Path is a directory"), diff --git a/tests/unit/drivers/image_generation/test_amazon_bedrock_stable_diffusion_image_generation_driver.py b/tests/unit/drivers/image_generation/test_amazon_bedrock_stable_diffusion_image_generation_driver.py index a2c51f58b..9aa4d3f4f 100644 --- a/tests/unit/drivers/image_generation/test_amazon_bedrock_stable_diffusion_image_generation_driver.py +++ b/tests/unit/drivers/image_generation/test_amazon_bedrock_stable_diffusion_image_generation_driver.py @@ -7,18 +7,18 @@ class TestAmazonBedrockImageGenerationDriver: - @pytest.fixture + @pytest.fixture() def bedrock_client(self): return Mock() - @pytest.fixture + @pytest.fixture() def session(self, bedrock_client): session = Mock() session.client.return_value = bedrock_client return session - @pytest.fixture + @pytest.fixture() def model_driver(self): model_driver = Mock() model_driver.text_to_image_request_parameters.return_value = {} @@ -26,7 +26,7 @@ def model_driver(self): return model_driver - @pytest.fixture + @pytest.fixture() def driver(self, session, model_driver): return AmazonBedrockImageGenerationDriver( session=session, model="stability.stable-diffusion-xl-v1", image_generation_model_driver=model_driver @@ -37,7 +37,7 @@ def test_init(self, driver): def test_init_requires_image_generation_model_driver(self, session): with pytest.raises(TypeError): - AmazonBedrockImageGenerationDriver(session=session, model="stability.stable-diffusion-xl-v1") # pyright: ignore + AmazonBedrockImageGenerationDriver(session=session, model="stability.stable-diffusion-xl-v1") # pyright: ignore[reportCallIssue] def test_try_text_to_image(self, driver): driver.bedrock_client.invoke_model.return_value = { diff --git a/tests/unit/drivers/image_generation/test_azure_openai_image_generation_driver.py b/tests/unit/drivers/image_generation/test_azure_openai_image_generation_driver.py index 2166bc28a..268708b2b 100644 --- a/tests/unit/drivers/image_generation/test_azure_openai_image_generation_driver.py +++ b/tests/unit/drivers/image_generation/test_azure_openai_image_generation_driver.py @@ -1,10 +1,12 @@ -import pytest from unittest.mock import Mock + +import pytest + from griptape.drivers import AzureOpenAiImageGenerationDriver class TestAzureOpenAiImageGenerationDriver: - @pytest.fixture + @pytest.fixture() def driver(self): return AzureOpenAiImageGenerationDriver( model="dall-e-3", @@ -27,7 +29,7 @@ def test_init_requires_endpoint(self): with pytest.raises(TypeError): AzureOpenAiImageGenerationDriver( model="dall-e-3", client=Mock(), azure_deployment="dalle-deployment", image_size="512x512" - ) # pyright: ignore + ) # pyright: ignore[reportCallIssues] def test_try_text_to_image(self, driver): driver.client.images.generate.return_value = Mock(data=[Mock(b64_json=b"aW1hZ2UgZGF0YQ==")]) diff --git a/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py b/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py index 971c39b89..2df6c6499 100644 --- a/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py +++ b/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py @@ -1,12 +1,12 @@ -from griptape.drivers import DummyImageGenerationDriver -from griptape.artifacts import ImageArtifact import pytest +from griptape.artifacts import ImageArtifact +from griptape.drivers import DummyImageGenerationDriver from griptape.exceptions import DummyException class TestDummyImageGenerationDriver: - @pytest.fixture + @pytest.fixture() def image_generation_driver(self): return DummyImageGenerationDriver() diff --git a/tests/unit/drivers/image_generation/test_leonardo_image_generation_driver.py b/tests/unit/drivers/image_generation/test_leonardo_image_generation_driver.py index 564d3616a..48805cde6 100644 --- a/tests/unit/drivers/image_generation/test_leonardo_image_generation_driver.py +++ b/tests/unit/drivers/image_generation/test_leonardo_image_generation_driver.py @@ -1,11 +1,13 @@ import uuid -from unittest.mock import Mock, PropertyMock, MagicMock +from unittest.mock import Mock + import pytest + from griptape.drivers import LeonardoImageGenerationDriver class TestLeonardoImageGenerationDriver: - @pytest.fixture + @pytest.fixture() def driver(self): requests_session = Mock() diff --git a/tests/unit/drivers/image_generation/test_openai_image_generation_driver.py b/tests/unit/drivers/image_generation/test_openai_image_generation_driver.py index 8ca488eb1..16bcd2870 100644 --- a/tests/unit/drivers/image_generation/test_openai_image_generation_driver.py +++ b/tests/unit/drivers/image_generation/test_openai_image_generation_driver.py @@ -1,10 +1,12 @@ -import pytest from unittest.mock import Mock + +import pytest + from griptape.drivers import OpenAiImageGenerationDriver class TestOpenAiImageGenerationDriver: - @pytest.fixture + @pytest.fixture() def driver(self): return OpenAiImageGenerationDriver(model="dall-e-2", client=Mock(), quality="hd", image_size="512x512") diff --git a/tests/unit/drivers/image_generation_model/test_bedrock_stable_diffusion_image_model_driver.py b/tests/unit/drivers/image_generation_model/test_bedrock_stable_diffusion_image_model_driver.py index cdd4e95b7..60583455e 100644 --- a/tests/unit/drivers/image_generation_model/test_bedrock_stable_diffusion_image_model_driver.py +++ b/tests/unit/drivers/image_generation_model/test_bedrock_stable_diffusion_image_model_driver.py @@ -7,15 +7,15 @@ class TestBedrockStableDiffusionImageGenerationModelDriver: - @pytest.fixture + @pytest.fixture() def model_driver(self): return BedrockStableDiffusionImageGenerationModelDriver() - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact(b"image", format="png", width=1024, height=1024) - @pytest.fixture + @pytest.fixture() def mask_artifact(self): return ImageArtifact(b"mask", format="png", width=1024, height=1024) @@ -118,5 +118,5 @@ def test_get_generated_image_failed(self, model_driver): response = {"artifacts": [{"finishReason": "ERROR", "base64": base64.b64encode(image_bytes).decode("utf-8")}]} - with pytest.raises(Exception): + with pytest.raises(Exception, match="Image generation failed:"): model_driver.get_generated_image(response) diff --git a/tests/unit/drivers/image_generation_model/test_bedrock_titan_image_model_driver.py b/tests/unit/drivers/image_generation_model/test_bedrock_titan_image_model_driver.py index 8c4ed40e3..6bf4c30d5 100644 --- a/tests/unit/drivers/image_generation_model/test_bedrock_titan_image_model_driver.py +++ b/tests/unit/drivers/image_generation_model/test_bedrock_titan_image_model_driver.py @@ -5,15 +5,15 @@ class TestBedrockTitanImageGenerationModelDriver: - @pytest.fixture + @pytest.fixture() def model_driver(self): return BedrockTitanImageGenerationModelDriver() - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact(b"image", format="png", width=1024, height=512) - @pytest.fixture + @pytest.fixture() def mask_artifact(self): return ImageArtifact(b"mask", format="png", width=1024, height=512) diff --git a/tests/unit/drivers/image_query/test_amazon_bedrock_image_query_driver.py b/tests/unit/drivers/image_query/test_amazon_bedrock_image_query_driver.py index 57336e8ea..9493ab23d 100644 --- a/tests/unit/drivers/image_query/test_amazon_bedrock_image_query_driver.py +++ b/tests/unit/drivers/image_query/test_amazon_bedrock_image_query_driver.py @@ -1,23 +1,25 @@ -import pytest import io from unittest.mock import Mock -from griptape.drivers import AmazonBedrockImageQueryDriver + +import pytest + from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.drivers import AmazonBedrockImageQueryDriver class TestAmazonBedrockImageQueryDriver: - @pytest.fixture + @pytest.fixture() def bedrock_client(self, mocker): return Mock() - @pytest.fixture + @pytest.fixture() def session(self, bedrock_client): session = Mock() session.client.return_value = bedrock_client return session - @pytest.fixture + @pytest.fixture() def model_driver(self): model_driver = Mock() model_driver.image_query_request_parameters.return_value = {} @@ -25,7 +27,7 @@ def model_driver(self): return model_driver - @pytest.fixture + @pytest.fixture() def image_query_driver(self, session, model_driver): return AmazonBedrockImageQueryDriver(session=session, model="model", image_query_model_driver=model_driver) diff --git a/tests/unit/drivers/image_query/test_anthropic_image_query_driver.py b/tests/unit/drivers/image_query/test_anthropic_image_query_driver.py index 24958d58f..db4b2407c 100644 --- a/tests/unit/drivers/image_query/test_anthropic_image_query_driver.py +++ b/tests/unit/drivers/image_query/test_anthropic_image_query_driver.py @@ -1,12 +1,14 @@ -import pytest import base64 from unittest.mock import Mock -from griptape.drivers import AnthropicImageQueryDriver + +import pytest + from griptape.artifacts import ImageArtifact +from griptape.drivers import AnthropicImageQueryDriver class TestAnthropicImageQueryDriver: - @pytest.fixture + @pytest.fixture() def mock_client(self, mocker): mock_client = mocker.patch("anthropic.Anthropic") return_value = Mock(text="Content") @@ -55,7 +57,7 @@ def test_try_query_max_tokens_value(self, mock_client): assert text_artifact.value == "Content" def test_try_query_max_tokens_none(self, mock_client): - driver = AnthropicImageQueryDriver(model="test-model", max_tokens=None) # pyright: ignore + driver = AnthropicImageQueryDriver(model="test-model", max_tokens=None) # pyright: ignore[reportArgumentType] test_prompt_string = "Prompt String" test_binary_data = b"test-data" with pytest.raises(TypeError): diff --git a/tests/unit/drivers/image_query/test_azure_openai_image_query_driver.py b/tests/unit/drivers/image_query/test_azure_openai_image_query_driver.py index a44319861..a1d428197 100644 --- a/tests/unit/drivers/image_query/test_azure_openai_image_query_driver.py +++ b/tests/unit/drivers/image_query/test_azure_openai_image_query_driver.py @@ -1,11 +1,13 @@ -import pytest from unittest.mock import Mock -from griptape.drivers import AzureOpenAiImageQueryDriver + +import pytest + from griptape.artifacts import ImageArtifact +from griptape.drivers import AzureOpenAiImageQueryDriver class TestAzureOpenAiVisionImageQueryDriver: - @pytest.fixture + @pytest.fixture() def mock_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create mock_choice = Mock(message=Mock(content="expected_output_text")) @@ -52,7 +54,7 @@ def test_try_query_multiple_choices(self, mock_completion_create): azure_endpoint="test-endpoint", azure_deployment="test-deployment", model="gpt-4" ) - with pytest.raises(Exception): + with pytest.raises(Exception, match="Image query responses with more than one choice are not supported yet."): driver.try_query("Prompt String", [ImageArtifact(value=b"test-data", width=100, height=100, format="png")]) def _expected_messages(self, expected_prompt_string, expected_binary_data): diff --git a/tests/unit/drivers/image_query/test_dummy_image_query_driver.py b/tests/unit/drivers/image_query/test_dummy_image_query_driver.py index 8efcfa749..02b69595f 100644 --- a/tests/unit/drivers/image_query/test_dummy_image_query_driver.py +++ b/tests/unit/drivers/image_query/test_dummy_image_query_driver.py @@ -1,12 +1,12 @@ -from griptape.drivers import DummyImageQueryDriver -from griptape.artifacts import ImageArtifact import pytest +from griptape.artifacts import ImageArtifact +from griptape.drivers import DummyImageQueryDriver from griptape.exceptions import DummyException class TestDummyImageQueryDriver: - @pytest.fixture + @pytest.fixture() def image_query_driver(self): return DummyImageQueryDriver() diff --git a/tests/unit/drivers/image_query/test_openai_image_query_driver.py b/tests/unit/drivers/image_query/test_openai_image_query_driver.py index 08f0c70c9..9c4b011a6 100644 --- a/tests/unit/drivers/image_query/test_openai_image_query_driver.py +++ b/tests/unit/drivers/image_query/test_openai_image_query_driver.py @@ -1,11 +1,13 @@ -import pytest from unittest.mock import Mock -from griptape.drivers import OpenAiImageQueryDriver + +import pytest + from griptape.artifacts import ImageArtifact +from griptape.drivers import OpenAiImageQueryDriver class TestOpenAiVisionImageQueryDriver: - @pytest.fixture + @pytest.fixture() def mock_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create mock_choice = Mock(message=Mock(content="expected_output_text")) @@ -43,7 +45,7 @@ def test_try_query_multiple_choices(self, mock_completion_create): mock_completion_create.return_value.choices.append(Mock(message=Mock(content="expected_output_text2"))) driver = OpenAiImageQueryDriver(model="gpt-4-vision-preview") - with pytest.raises(Exception): + with pytest.raises(Exception, match="Image query responses with more than one choice are not supported yet."): driver.try_query("Prompt String", [ImageArtifact(value=b"test-data", width=100, height=100, format="png")]) def _expected_messages(self, expected_prompt_string, expected_binary_data): diff --git a/tests/unit/drivers/image_query_models/test_bedrock_claude_image_query_model_driver.py b/tests/unit/drivers/image_query_models/test_bedrock_claude_image_query_model_driver.py index 14fa8ff28..c274f71dd 100644 --- a/tests/unit/drivers/image_query_models/test_bedrock_claude_image_query_model_driver.py +++ b/tests/unit/drivers/image_query_models/test_bedrock_claude_image_query_model_driver.py @@ -1,6 +1,7 @@ import pytest -from griptape.drivers import BedrockClaudeImageQueryModelDriver + from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.drivers import BedrockClaudeImageQueryModelDriver class TestBedrockClaudeImageQueryModelDriver: diff --git a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py index ba79a4def..8e700d0a5 100644 --- a/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_dynamodb_conversation_memory_driver.py @@ -1,12 +1,13 @@ +import boto3 import pytest from moto import mock_dynamodb -import boto3 -from tests.mocks.mock_prompt_driver import MockPromptDriver -from tests.utils.aws import mock_aws_credentials + +from griptape.drivers import AmazonDynamoDbConversationMemoryDriver from griptape.memory.structure import ConversationMemory -from griptape.tasks import PromptTask from griptape.structures import Pipeline -from griptape.drivers import AmazonDynamoDbConversationMemoryDriver +from griptape.tasks import PromptTask +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.utils.aws import mock_aws_credentials class TestDynamoDbConversationMemoryDriver: @@ -17,7 +18,7 @@ class TestDynamoDbConversationMemoryDriver: PARTITION_KEY_VALUE = "bar" @pytest.fixture(autouse=True) - def run_before_and_after_tests(self): + def _run_before_and_after_tests(self): mock_aws_credentials() self.mock_dynamodb = mock_dynamodb() self.mock_dynamodb.start() diff --git a/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py index c794afd0e..e1a383ab9 100644 --- a/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_local_conversation_memory_driver.py @@ -1,17 +1,20 @@ +import contextlib import os + import pytest -from tests.mocks.mock_prompt_driver import MockPromptDriver + from griptape.drivers import LocalConversationMemoryDriver from griptape.memory.structure import ConversationMemory -from griptape.tasks import PromptTask from griptape.structures import Pipeline +from griptape.tasks import PromptTask +from tests.mocks.mock_prompt_driver import MockPromptDriver class TestLocalConversationMemoryDriver: MEMORY_FILE_PATH = "test_memory.json" @pytest.fixture(autouse=True) - def run_before_and_after_tests(self): + def _run_before_and_after_tests(self): self.__delete_file(self.MEMORY_FILE_PATH) yield @@ -28,7 +31,7 @@ def test_store(self): try: with open(self.MEMORY_FILE_PATH): - assert False + raise AssertionError() except FileNotFoundError: assert True @@ -74,8 +77,6 @@ def test_autoload(self): assert autoloaded_memory.runs[0].input.value == "test" assert autoloaded_memory.runs[0].output.value == "mock output" - def __delete_file(self, file_path): - try: + def __delete_file(self, file_path) -> None: + with contextlib.suppress(FileNotFoundError): os.remove(file_path) - except FileNotFoundError: - pass diff --git a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py index 1af9d74dc..4a92a28a8 100644 --- a/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py +++ b/tests/unit/drivers/memory/conversation/test_redis_conversation_memory_driver.py @@ -1,7 +1,8 @@ import pytest import redis -from griptape.memory.structure.base_conversation_memory import BaseConversationMemory + from griptape.drivers.memory.conversation.redis_conversation_memory_driver import RedisConversationMemoryDriver +from griptape.memory.structure.base_conversation_memory import BaseConversationMemory TEST_CONVERSATION = '{"type": "ConversationMemory", "runs": [{"type": "Run", "id": "729ca6be5d79433d9762eb06dfd677e2", "input": {"type": "TextArtifact", "id": "1234", "value": "Hi There, Hello"}, "output": {"type": "TextArtifact", "id": "123", "value": "Hello! How can I assist you today?"}}], "max_runs": 2}' CONVERSATION_ID = "117151897f344ff684b553d0655d8f39" @@ -13,7 +14,7 @@ class TestRedisConversationMemoryDriver: @pytest.fixture(autouse=True) - def mock_redis(self, mocker): + def _mock_redis(self, mocker): mocker.patch.object(redis.StrictRedis, "hset", return_value=None) mocker.patch.object(redis.StrictRedis, "keys", return_value=[b"test"]) mocker.patch.object(redis.StrictRedis, "hget", return_value=TEST_CONVERSATION) @@ -25,13 +26,13 @@ def mock_redis(self, mocker): mocker.patch.object(redis.StrictRedis, "ft", return_value=fake_redisearch) - @pytest.fixture + @pytest.fixture() def driver(self): return RedisConversationMemoryDriver(host=HOST, port=PORT, db=0, index=INDEX, conversation_id=CONVERSATION_ID) def test_store(self, driver): memory = BaseConversationMemory.from_json(TEST_CONVERSATION) - assert driver.store(memory) == None + assert driver.store(memory) is None def test_load(self, driver): memory = driver.load() diff --git a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py index e31b6a448..6a58b09dc 100644 --- a/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_bedrock_prompt_driver.py @@ -1,10 +1,8 @@ import pytest -from griptape.artifacts import ImageArtifact, TextArtifact, ListArtifact, ErrorArtifact, ActionArtifact -from griptape.common import PromptStack -from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction +from griptape.artifacts import ActionArtifact, ErrorArtifact, ImageArtifact, ListArtifact, TextArtifact +from griptape.common import ActionCallDeltaMessageContent, PromptStack, TextDeltaMessageContent, ToolAction from griptape.drivers import AmazonBedrockPromptDriver - from tests.mocks.mock_tool.tool import MockTool @@ -159,7 +157,7 @@ class TestAmazonBedrockPromptDriver: }, ] - @pytest.fixture + @pytest.fixture() def mock_converse(self, mocker): mock_converse = mocker.patch("boto3.Session").return_value.client.return_value.converse @@ -177,7 +175,7 @@ def mock_converse(self, mocker): return mock_converse - @pytest.fixture + @pytest.fixture() def mock_converse_stream(self, mocker): mock_converse_stream = mocker.patch("boto3.Session").return_value.client.return_value.converse_stream @@ -275,7 +273,7 @@ def prompt_stack(self, request): return prompt_stack - @pytest.fixture + @pytest.fixture() def messages(self): return [ {"role": "user", "content": [{"text": "user-input"}]}, diff --git a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py index a75fc6ed0..e74797e42 100644 --- a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py @@ -1,11 +1,13 @@ +import json +from io import BytesIO from typing import Any + +import pytest from botocore.response import StreamingBody -from griptape.tokenizers import HuggingFaceTokenizer -from griptape.drivers.prompt.amazon_sagemaker_jumpstart_prompt_driver import AmazonSageMakerJumpstartPromptDriver + from griptape.common import PromptStack -from io import BytesIO -import json -import pytest +from griptape.drivers.prompt.amazon_sagemaker_jumpstart_prompt_driver import AmazonSageMakerJumpstartPromptDriver +from griptape.tokenizers import HuggingFaceTokenizer def to_streaming_body(data: Any) -> StreamingBody: diff --git a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py index e8f6d337f..3b1343336 100644 --- a/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_anthropic_prompt_driver.py @@ -1,10 +1,11 @@ -from griptape.artifacts.error_artifact import ErrorArtifact -from griptape.drivers import AnthropicPromptDriver -from griptape.common import PromptStack, TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction -from griptape.artifacts import TextArtifact, ActionArtifact, ImageArtifact, ListArtifact from unittest.mock import Mock + import pytest +from griptape.artifacts import ActionArtifact, ImageArtifact, ListArtifact, TextArtifact +from griptape.artifacts.error_artifact import ErrorArtifact +from griptape.common import ActionCallDeltaMessageContent, PromptStack, TextDeltaMessageContent, ToolAction +from griptape.drivers import AnthropicPromptDriver from tests.mocks.mock_tool.tool import MockTool @@ -131,7 +132,7 @@ class TestAnthropicPromptDriver: }, ] - @pytest.fixture + @pytest.fixture() def mock_client(self, mocker): mock_client = mocker.patch("anthropic.Anthropic") mock_tool_use = Mock(type="tool_use", id="mock-id", input={"foo": "bar"}) @@ -150,7 +151,7 @@ def mock_client(self, mocker): return mock_client - @pytest.fixture + @pytest.fixture() def mock_stream_client(self, mocker): mock_stream_client = mocker.patch("anthropic.Anthropic") @@ -263,7 +264,7 @@ def prompt_stack(self, request): return prompt_stack - @pytest.fixture + @pytest.fixture() def messages(self): return [ {"role": "user", "content": "user-input"}, diff --git a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py index 9e56b39bd..dc0b54b0a 100644 --- a/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_azure_openai_chat_prompt_driver.py @@ -1,13 +1,15 @@ -import pytest -from griptape.artifacts import TextArtifact, ActionArtifact from unittest.mock import Mock + +import pytest + +from griptape.artifacts import ActionArtifact, TextArtifact +from griptape.common import ActionCallDeltaMessageContent, TextDeltaMessageContent from griptape.drivers import AzureOpenAiChatPromptDriver -from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent from tests.unit.drivers.prompt.test_openai_chat_prompt_driver import TestOpenAiChatPromptDriverFixtureMixin class TestAzureOpenAiChatPromptDriver(TestOpenAiChatPromptDriverFixtureMixin): - @pytest.fixture + @pytest.fixture() def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create mock_function = Mock(arguments='{"foo": "bar"}', id="mock-id") @@ -22,7 +24,7 @@ def mock_chat_completion_create(self, mocker): return mock_chat_create - @pytest.fixture + @pytest.fixture() def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.AzureOpenAI").return_value.chat.completions.create mock_tool_call_delta_header = Mock() diff --git a/tests/unit/drivers/prompt/test_base_prompt_driver.py b/tests/unit/drivers/prompt/test_base_prompt_driver.py index 6eb000e1f..3c2bb333e 100644 --- a/tests/unit/drivers/prompt/test_base_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_base_prompt_driver.py @@ -1,11 +1,11 @@ +from griptape.artifacts import ErrorArtifact, TextArtifact +from griptape.common import PromptStack from griptape.common.prompt_stack.messages.message import Message from griptape.events import FinishPromptEvent, StartPromptEvent -from griptape.common import PromptStack -from tests.mocks.mock_prompt_driver import MockPromptDriver -from tests.mocks.mock_failing_prompt_driver import MockFailingPromptDriver -from griptape.artifacts import ErrorArtifact, TextArtifact -from griptape.tasks import PromptTask from griptape.structures import Pipeline +from griptape.tasks import PromptTask +from tests.mocks.mock_failing_prompt_driver import MockFailingPromptDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver class TestBasePromptDriver: diff --git a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py index 167c08b34..c642b7ee0 100644 --- a/tests/unit/drivers/prompt/test_cohere_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_cohere_prompt_driver.py @@ -5,9 +5,8 @@ from griptape.artifacts.action_artifact import ActionArtifact from griptape.artifacts.list_artifact import ListArtifact from griptape.artifacts.text_artifact import TextArtifact -from griptape.common import PromptStack, ToolAction +from griptape.common import ActionCallDeltaMessageContent, PromptStack, TextDeltaMessageContent, ToolAction from griptape.drivers import CoherePromptDriver -from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent from tests.mocks.mock_tool.tool import MockTool @@ -42,7 +41,7 @@ class TestCoherePromptDriver: }, ] - @pytest.fixture + @pytest.fixture() def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value mock_tool_call = Mock(parameters={"foo": "bar"}) @@ -53,7 +52,7 @@ def mock_client(self, mocker): return mock_client - @pytest.fixture + @pytest.fixture() def mock_stream_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value mock_tool_call_delta_header = Mock() diff --git a/tests/unit/drivers/prompt/test_dummy_prompt_driver.py b/tests/unit/drivers/prompt/test_dummy_prompt_driver.py index d569b55af..203bad3d5 100644 --- a/tests/unit/drivers/prompt/test_dummy_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_dummy_prompt_driver.py @@ -1,11 +1,11 @@ -from griptape.drivers import DummyPromptDriver import pytest +from griptape.drivers import DummyPromptDriver from griptape.exceptions import DummyException class TestDummyPromptDriver: - @pytest.fixture + @pytest.fixture() def prompt_driver(self): return DummyPromptDriver() diff --git a/tests/unit/drivers/prompt/test_google_prompt_driver.py b/tests/unit/drivers/prompt/test_google_prompt_driver.py index b1a72d10d..478ef8fb9 100644 --- a/tests/unit/drivers/prompt/test_google_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_google_prompt_driver.py @@ -1,15 +1,15 @@ -from google.generativeai.types import ContentDict, GenerationConfig +from unittest.mock import Mock + +import pytest from google.generativeai.protos import FunctionCall, FunctionResponse, Part -from griptape.artifacts import TextArtifact, ImageArtifact, ActionArtifact +from google.generativeai.types import ContentDict, GenerationConfig +from google.protobuf.json_format import MessageToDict + +from griptape.artifacts import ActionArtifact, ImageArtifact, TextArtifact from griptape.artifacts.list_artifact import ListArtifact -from griptape.common import TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction +from griptape.common import ActionCallDeltaMessageContent, PromptStack, TextDeltaMessageContent, ToolAction from griptape.drivers import GooglePromptDriver -from griptape.common import PromptStack -from unittest.mock import Mock from tests.mocks.mock_tool.tool import MockTool -from google.protobuf.json_format import MessageToDict - -import pytest class TestGooglePromptDriver: @@ -43,7 +43,7 @@ class TestGooglePromptDriver: }, ] - @pytest.fixture + @pytest.fixture() def mock_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") mock_function_call = Mock(type="tool_use", id="MockTool_test", args={"foo": "bar"}) @@ -55,7 +55,7 @@ def mock_generative_model(self, mocker): return mock_generative_model - @pytest.fixture + @pytest.fixture() def mock_stream_generative_model(self, mocker): mock_generative_model = mocker.patch("google.generativeai.GenerativeModel") mock_function_call_delta = Mock(type="tool_use", id="MockTool_test", args={"foo": "bar"}) @@ -117,7 +117,7 @@ def prompt_stack(self, request): return prompt_stack - @pytest.fixture + @pytest.fixture() def messages(self): return [ {"parts": ["user-input"], "role": "user"}, diff --git a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py index ec7ea73f8..1a4e1b25b 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_hub_prompt_driver.py @@ -1,10 +1,11 @@ -from griptape.drivers import HuggingFaceHubPromptDriver -from griptape.common import PromptStack, TextDeltaMessageContent import pytest +from griptape.common import PromptStack, TextDeltaMessageContent +from griptape.drivers import HuggingFaceHubPromptDriver + class TestHuggingFaceHubPromptDriver: - @pytest.fixture + @pytest.fixture() def mock_client(self, mocker): mock_client = mocker.patch("huggingface_hub.InferenceClient").return_value @@ -20,14 +21,14 @@ def tokenizer(self, mocker): return tokenizer - @pytest.fixture + @pytest.fixture() def mock_client_stream(self, mocker): mock_client = mocker.patch("huggingface_hub.InferenceClient").return_value mock_client.text_generation.return_value = iter(["model-output"]) return mock_client - @pytest.fixture + @pytest.fixture() def prompt_stack(self): prompt_stack = PromptStack() prompt_stack.add_system_message("system-input") diff --git a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py index a63d697fb..5323f5d2d 100644 --- a/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_hugging_face_pipeline_prompt_driver.py @@ -1,7 +1,8 @@ -from griptape.drivers import HuggingFacePipelinePromptDriver -from griptape.common import PromptStack import pytest +from griptape.common import PromptStack +from griptape.drivers import HuggingFacePipelinePromptDriver + class TestHuggingFacePipelinePromptDriver: @pytest.fixture(autouse=True) @@ -25,7 +26,7 @@ def mock_autotokenizer(self, mocker): mock_autotokenizer.encode.return_value = [1, 2, 3] return mock_autotokenizer - @pytest.fixture + @pytest.fixture() def prompt_stack(self): prompt_stack = PromptStack() prompt_stack.add_system_message("system-input") diff --git a/tests/unit/drivers/prompt/test_ollama_prompt_driver.py b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py index a247a77ab..e51da368a 100644 --- a/tests/unit/drivers/prompt/test_ollama_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_ollama_prompt_driver.py @@ -1,12 +1,13 @@ +import pytest + +from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact +from griptape.common import PromptStack from griptape.common.prompt_stack.contents.text_delta_message_content import TextDeltaMessageContent from griptape.drivers import OllamaPromptDriver -from griptape.common import PromptStack -from griptape.artifacts import ImageArtifact, ListArtifact, TextArtifact -import pytest class TestOllamaPromptDriver: - @pytest.fixture + @pytest.fixture() def mock_client(self, mocker): mock_client = mocker.patch("ollama.Client") @@ -14,7 +15,7 @@ def mock_client(self, mocker): return mock_client - @pytest.fixture + @pytest.fixture() def mock_stream_client(self, mocker): mock_stream_client = mocker.patch("ollama.Client") mock_stream_client.return_value.chat.return_value = iter([{"message": {"content": "model-output"}}]) diff --git a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py index 59772ff23..23a40e20c 100644 --- a/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_openai_chat_prompt_driver.py @@ -1,12 +1,13 @@ -from griptape.artifacts import ImageArtifact, ListArtifact -from griptape.artifacts import TextArtifact, ActionArtifact +from unittest.mock import Mock + +import pytest + +from griptape.artifacts import ActionArtifact, ImageArtifact, ListArtifact, TextArtifact +from griptape.common import ActionCallDeltaMessageContent, PromptStack, TextDeltaMessageContent, ToolAction from griptape.drivers import OpenAiChatPromptDriver -from griptape.common import PromptStack, TextDeltaMessageContent, ActionCallDeltaMessageContent, ToolAction from griptape.tokenizers import OpenAiTokenizer -from unittest.mock import Mock from tests.mocks.mock_tokenizer import MockTokenizer from tests.mocks.mock_tool.tool import MockTool -import pytest class TestOpenAiChatPromptDriverFixtureMixin: @@ -153,7 +154,7 @@ class TestOpenAiChatPromptDriverFixtureMixin: }, ] - @pytest.fixture + @pytest.fixture() def mock_chat_completion_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create mock_function = Mock(arguments='{"foo": "bar"}', id="mock-id") @@ -168,7 +169,7 @@ def mock_chat_completion_create(self, mocker): return mock_chat_create - @pytest.fixture + @pytest.fixture() def mock_chat_completion_stream_create(self, mocker): mock_chat_create = mocker.patch("openai.OpenAI").return_value.chat.completions.create mock_tool_call_delta_header = Mock() @@ -206,7 +207,7 @@ def mock_chat_completion_stream_create(self, mocker): ) return mock_chat_create - @pytest.fixture + @pytest.fixture() def prompt_stack(self): prompt_stack = PromptStack() prompt_stack.tools = [MockTool()] @@ -244,7 +245,7 @@ def prompt_stack(self): ) return prompt_stack - @pytest.fixture + @pytest.fixture() def messages(self): return [ {"role": "system", "content": "system-input"}, @@ -283,7 +284,7 @@ def __init__( remaining_tokens=234, limit_requests=345, limit_tokens=456, - ): + ) -> None: self.reset_requests_in = reset_requests_in self.reset_requests_in_unit = reset_requests_in_unit self.reset_tokens_in = reset_tokens_in diff --git a/tests/unit/drivers/rerank/test_cohere_rerank_driver.py b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py index 952546e5a..87a727269 100644 --- a/tests/unit/drivers/rerank/test_cohere_rerank_driver.py +++ b/tests/unit/drivers/rerank/test_cohere_rerank_driver.py @@ -1,11 +1,12 @@ import pytest -from cohere import RerankResponseResultsItemDocument, RerankResponseResultsItem +from cohere import RerankResponseResultsItem, RerankResponseResultsItemDocument + from griptape.artifacts import TextArtifact from griptape.drivers import CohereRerankDriver class TestCohereRerankDriver: - @pytest.fixture + @pytest.fixture() def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value mock_client.rerank.return_value.results = [ diff --git a/tests/unit/drivers/sql/test_amazon_redshift_sql_driver.py b/tests/unit/drivers/sql/test_amazon_redshift_sql_driver.py index d67e1c557..966df481c 100644 --- a/tests/unit/drivers/sql/test_amazon_redshift_sql_driver.py +++ b/tests/unit/drivers/sql/test_amazon_redshift_sql_driver.py @@ -1,7 +1,8 @@ -import pytest import boto3 +import pytest from botocore.stub import Stubber -from griptape.drivers import BaseSqlDriver, AmazonRedshiftSqlDriver + +from griptape.drivers import AmazonRedshiftSqlDriver, BaseSqlDriver class TestAmazonRedshiftSqlDriver: @@ -41,7 +42,7 @@ class TestAmazonRedshiftSqlDriver: }, ] - @pytest.fixture + @pytest.fixture() def statement_driver(self): session = boto3.Session(region_name="us-east-1") client = session.client("redshift-data") @@ -108,7 +109,7 @@ def statement_driver(self): return AmazonRedshiftSqlDriver(database="dev", session=session, workgroup_name="dev", client=client) - @pytest.fixture + @pytest.fixture() def describe_table_driver(self): session = boto3.Session(region_name="us-east-1") client = session.client("redshift-data") diff --git a/tests/unit/drivers/sql/test_snowflake_sql_driver.py b/tests/unit/drivers/sql/test_snowflake_sql_driver.py index 91403a467..055b1e744 100644 --- a/tests/unit/drivers/sql/test_snowflake_sql_driver.py +++ b/tests/unit/drivers/sql/test_snowflake_sql_driver.py @@ -1,8 +1,10 @@ from dataclasses import dataclass from unittest import mock + import pytest -from sqlalchemy import create_engine from snowflake.connector import SnowflakeConnection +from sqlalchemy import create_engine + from griptape.drivers import BaseSqlDriver, SnowflakeSqlDriver @@ -11,7 +13,7 @@ class TestSnowflakeSqlDriver: TEST_COLUMNS = [("first_name", "VARCHAR"), ("last_name", "VARCHAR")] - @pytest.fixture + @pytest.fixture() def mock_table(self, mocker): @dataclass class Column: @@ -21,13 +23,13 @@ class Column: mock_table = mocker.MagicMock(name="table", columns=[Column("first_name"), Column("last_name")]) return mock_table - @pytest.fixture + @pytest.fixture() def mock_metadata(self, mocker): mock_meta = mocker.MagicMock(name="metadata") mock_meta.reflect.return_value = None return mock_meta - @pytest.fixture + @pytest.fixture() def mock_snowflake_engine(self, mocker): mock_engine = mocker.MagicMock(name="engine") result_mock = mocker.MagicMock(name="result") @@ -44,22 +46,22 @@ def mock_snowflake_engine(self, mocker): return mock_engine - @pytest.fixture + @pytest.fixture() def mock_snowflake_connection(self, mocker): mock_connection = mocker.MagicMock(spec=SnowflakeConnection, name="connection") return mock_connection - @pytest.fixture + @pytest.fixture() def mock_snowflake_connection_no_schema(self, mocker): mock_connection = mocker.MagicMock(spec=SnowflakeConnection, name="connection_no_schema", schema=None) return mock_connection - @pytest.fixture + @pytest.fixture() def mock_snowflake_connection_no_database(self, mocker): mock_connection = mocker.MagicMock(spec=SnowflakeConnection, name="connection_no_database", database=None) return mock_connection - @pytest.fixture + @pytest.fixture() def driver(self, mock_snowflake_engine, mock_snowflake_connection): def get_connection(): return mock_snowflake_connection diff --git a/tests/unit/drivers/sql/test_sql_driver.py b/tests/unit/drivers/sql/test_sql_driver.py index d4caf6f50..742acd0b2 100644 --- a/tests/unit/drivers/sql/test_sql_driver.py +++ b/tests/unit/drivers/sql/test_sql_driver.py @@ -1,9 +1,10 @@ import pytest + from griptape.drivers import SqlDriver class TestSqlDriver: - @pytest.fixture + @pytest.fixture() def driver(self): new_driver = SqlDriver(engine_url="sqlite:///:memory:") diff --git a/tests/unit/drivers/structure_run/test_griptape_cloud_structure_run_driver.py b/tests/unit/drivers/structure_run/test_griptape_cloud_structure_run_driver.py index b056241ec..bdd5cd3ed 100644 --- a/tests/unit/drivers/structure_run/test_griptape_cloud_structure_run_driver.py +++ b/tests/unit/drivers/structure_run/test_griptape_cloud_structure_run_driver.py @@ -1,9 +1,10 @@ import pytest -from griptape.artifacts import TextArtifact, InfoArtifact + +from griptape.artifacts import InfoArtifact, TextArtifact class TestGriptapeCloudStructureRunDriver: - @pytest.fixture + @pytest.fixture() def driver(self, mocker): from griptape.drivers import GriptapeCloudStructureRunDriver diff --git a/tests/unit/drivers/structure_run/test_local_structure_run_driver.py b/tests/unit/drivers/structure_run/test_local_structure_run_driver.py index cb7b3058e..316f7bf71 100644 --- a/tests/unit/drivers/structure_run/test_local_structure_run_driver.py +++ b/tests/unit/drivers/structure_run/test_local_structure_run_driver.py @@ -1,11 +1,9 @@ import os -import pytest -from griptape.artifacts.text_artifact import TextArtifact + +from griptape.drivers import LocalStructureRunDriver +from griptape.structures import Agent, Pipeline from griptape.tasks import StructureRunTask -from griptape.structures import Agent from tests.mocks.mock_prompt_driver import MockPromptDriver -from griptape.drivers import LocalStructureRunDriver -from griptape.structures import Pipeline class TestLocalStructureRunDriver: @@ -22,8 +20,8 @@ def test_run(self): def test_run_with_env(self): pipeline = Pipeline() - agent = Agent(prompt_driver=MockPromptDriver(mock_output=lambda _: os.environ["key"])) - driver = LocalStructureRunDriver(structure_factory_fn=lambda: agent, env={"key": "value"}) + agent = Agent(prompt_driver=MockPromptDriver(mock_output=lambda _: os.environ["KEY"])) + driver = LocalStructureRunDriver(structure_factory_fn=lambda: agent, env={"KEY": "value"}) task = StructureRunTask(driver=driver) pipeline.add_task(task) diff --git a/tests/unit/drivers/text_to_speech/test_elevenlabs_audio_generation_driver.py b/tests/unit/drivers/text_to_speech/test_elevenlabs_audio_generation_driver.py index 2d90bc2f5..26c29adcf 100644 --- a/tests/unit/drivers/text_to_speech/test_elevenlabs_audio_generation_driver.py +++ b/tests/unit/drivers/text_to_speech/test_elevenlabs_audio_generation_driver.py @@ -1,10 +1,12 @@ -import pytest from unittest.mock import Mock + +import pytest + from griptape.drivers import ElevenLabsTextToSpeechDriver class TestElevenLabsTextToSpeechDriver: - @pytest.fixture + @pytest.fixture() def driver(self): return ElevenLabsTextToSpeechDriver(model="model", client=Mock(), voice="voice", api_key="key") diff --git a/tests/unit/drivers/transcription/test_openai_audio_transcription_driver.py b/tests/unit/drivers/transcription/test_openai_audio_transcription_driver.py index 57c5a5e2e..f9c22a725 100644 --- a/tests/unit/drivers/transcription/test_openai_audio_transcription_driver.py +++ b/tests/unit/drivers/transcription/test_openai_audio_transcription_driver.py @@ -1,16 +1,17 @@ -import pytest from unittest.mock import Mock +import pytest + from griptape.artifacts import AudioArtifact from griptape.drivers import OpenAiAudioTranscriptionDriver class TestOpenAiAudioTranscriptionDriver: - @pytest.fixture + @pytest.fixture() def audio_artifact(self): return AudioArtifact(value=b"audio data", format="mp3") - @pytest.fixture + @pytest.fixture() def driver(self): return OpenAiAudioTranscriptionDriver(model="model", client=Mock(), api_key="key") diff --git a/tests/unit/drivers/vector/test_amazon_opensearch_vector_store_driver.py b/tests/unit/drivers/vector/test_amazon_opensearch_vector_store_driver.py index b66cc057e..e5988b234 100644 --- a/tests/unit/drivers/vector/test_amazon_opensearch_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_amazon_opensearch_vector_store_driver.py @@ -1,12 +1,14 @@ +from unittest.mock import Mock, create_autospec, patch + +import boto3 +import numpy as np import pytest -from unittest.mock import patch, Mock, create_autospec + from griptape.drivers import AmazonOpenSearchVectorStoreDriver -import numpy as np -import boto3 class TestAmazonOpenSearchVectorStoreDriver: - @pytest.fixture + @pytest.fixture() def driver(self): mock_session = create_autospec(boto3.Session, instance=True) mock_driver = create_autospec(AmazonOpenSearchVectorStoreDriver, instance=True, session=mock_session) diff --git a/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py b/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py index b68486914..6dd4fa5e9 100644 --- a/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_azure_mongodb_vector_store_driver.py @@ -1,14 +1,13 @@ -import pytest import mongomock -from unittest.mock import patch -from pymongo.errors import OperationFailure +import pytest + from griptape.artifacts import TextArtifact from griptape.drivers import AzureMongoDbVectorStoreDriver, BaseVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestAzureMongoDbVectorStoreDriver: - @pytest.fixture + @pytest.fixture() def driver(self, monkeypatch): embedding_driver = MockEmbeddingDriver() return AzureMongoDbVectorStoreDriver( @@ -66,15 +65,18 @@ def test_load_entries(self, driver): vector = [0.5, 0.5, 0.5] driver.upsert_vector(vector, vector_id=vector_id_str) # ensure at least one entry exists results = list(driver.load_entries()) - assert results is not None and len(results) > 0 + assert results is not None + assert len(results) > 0 def test_delete(self, driver): vector_id_str = "123" vector = [0.5, 0.5, 0.5] driver.upsert_vector(vector, vector_id=vector_id_str) # ensure at least one entry exists results = list(driver.load_entries()) - assert results is not None and len(results) > 0 + assert results is not None + assert len(results) > 0 driver.delete_vector(vector_id_str) results = list(driver.load_entries()) - assert results is not None and len(results) == 0 + assert results is not None + assert len(results) == 0 diff --git a/tests/unit/drivers/vector/test_base_local_vector_store_driver.py b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py index 8c08292dd..ac4ff8043 100644 --- a/tests/unit/drivers/vector/test_base_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_base_local_vector_store_driver.py @@ -1,12 +1,14 @@ from abc import ABC, abstractmethod -import pytest from unittest.mock import patch + +import pytest + from griptape.artifacts import TextArtifact from griptape.artifacts.csv_row_artifact import CsvRowArtifact class BaseLocalVectorStoreDriver(ABC): - @pytest.fixture + @pytest.fixture() @abstractmethod def driver(self): ... diff --git a/tests/unit/drivers/vector/test_dummy_vector_store_driver.py b/tests/unit/drivers/vector/test_dummy_vector_store_driver.py index 720778c38..df4867212 100644 --- a/tests/unit/drivers/vector/test_dummy_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_dummy_vector_store_driver.py @@ -1,10 +1,11 @@ import pytest + from griptape.drivers import DummyVectorStoreDriver from griptape.exceptions import DummyException class TestDummyVectorStoreDriver: - @pytest.fixture + @pytest.fixture() def vector_store_driver(self): return DummyVectorStoreDriver() diff --git a/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py b/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py index 957edebb8..0f52ba6c5 100644 --- a/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py @@ -1,5 +1,7 @@ -import pytest import uuid + +import pytest + from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver @@ -10,7 +12,7 @@ class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: test_metas = [{"key": "value1"}, {"key": "value2"}] test_scores = [0.7, 0.8] - @pytest.fixture + @pytest.fixture() def driver(self, mocker): test_entries = { "entries": [ diff --git a/tests/unit/drivers/vector/test_local_vector_store_driver.py b/tests/unit/drivers/vector/test_local_vector_store_driver.py index 314f2fd6d..6f022793c 100644 --- a/tests/unit/drivers/vector/test_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_local_vector_store_driver.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts import TextArtifact from griptape.drivers import LocalVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -6,7 +7,7 @@ class TestLocalVectorStoreDriver(BaseLocalVectorStoreDriver): - @pytest.fixture + @pytest.fixture() def driver(self): return LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) diff --git a/tests/unit/drivers/vector/test_marqo_vector_store_driver.py b/tests/unit/drivers/vector/test_marqo_vector_store_driver.py index f42906035..5c2399bc5 100644 --- a/tests/unit/drivers/vector/test_marqo_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_marqo_vector_store_driver.py @@ -1,7 +1,9 @@ from collections import namedtuple + import pytest -from griptape.drivers import MarqoVectorStoreDriver + from griptape.artifacts import TextArtifact +from griptape.drivers import MarqoVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -79,7 +81,7 @@ def mock_marqo(self, mocker): # Return the mock_client for use in other fixtures return mock_client - @pytest.fixture + @pytest.fixture() def driver(self, mock_marqo): return MarqoVectorStoreDriver( api_key="foobar", diff --git a/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py b/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py index 5b9aeed06..20cb8bdc0 100644 --- a/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_mongodb_atlas_vector_store_driver.py @@ -1,14 +1,13 @@ -import pytest import mongomock -from unittest.mock import patch -from pymongo.errors import OperationFailure +import pytest + from griptape.artifacts import TextArtifact -from griptape.drivers import MongoDbAtlasVectorStoreDriver, BaseVectorStoreDriver +from griptape.drivers import BaseVectorStoreDriver, MongoDbAtlasVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestMongoDbAtlasVectorStoreDriver: - @pytest.fixture + @pytest.fixture() def driver(self, monkeypatch): embedding_driver = MockEmbeddingDriver() return MongoDbAtlasVectorStoreDriver( @@ -66,15 +65,18 @@ def test_load_entries(self, driver): vector = [0.5, 0.5, 0.5] driver.upsert_vector(vector, vector_id=vector_id_str) # ensure at least one entry exists results = list(driver.load_entries()) - assert results is not None and len(results) > 0 + assert results is not None + assert len(results) > 0 def test_delete(self, driver): vector_id_str = "123" vector = [0.5, 0.5, 0.5] driver.upsert_vector(vector, vector_id=vector_id_str) # ensure at least one entry exists results = list(driver.load_entries()) - assert results is not None and len(results) > 0 + assert results is not None + assert len(results) > 0 driver.delete_vector(vector_id_str) results = list(driver.load_entries()) - assert results is not None and len(results) == 0 + assert results is not None + assert len(results) == 0 diff --git a/tests/unit/drivers/vector/test_opensearch_vector_store_driver.py b/tests/unit/drivers/vector/test_opensearch_vector_store_driver.py index d2c967caf..cef3805ab 100644 --- a/tests/unit/drivers/vector/test_opensearch_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_opensearch_vector_store_driver.py @@ -1,11 +1,13 @@ +from unittest.mock import Mock, create_autospec, patch + +import numpy as np import pytest -from unittest.mock import patch, Mock, create_autospec + from griptape.drivers import OpenSearchVectorStoreDriver -import numpy as np class TestOpenSearchVectorStoreDriver: - @pytest.fixture + @pytest.fixture() def driver(self): mock_driver = create_autospec(OpenSearchVectorStoreDriver, instance=True) mock_driver.upsert_vector.return_value = "foo" diff --git a/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py index 8f6773fc1..c130858b5 100644 --- a/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_persistent_local_vector_store_driver.py @@ -1,6 +1,8 @@ import os import tempfile + import pytest + from griptape.artifacts import TextArtifact from griptape.drivers import LocalVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -8,12 +10,12 @@ class TestPersistentLocalVectorStoreDriver(BaseLocalVectorStoreDriver): - @pytest.fixture + @pytest.fixture() def temp_dir(self): with tempfile.TemporaryDirectory() as temp_dir: yield temp_dir - @pytest.fixture + @pytest.fixture() def driver(self, temp_dir): persist_file = os.path.join(temp_dir, "store.json") diff --git a/tests/unit/drivers/vector/test_pgvector_vector_store_driver.py b/tests/unit/drivers/vector/test_pgvector_vector_store_driver.py index 3854ea4f1..29b5ad82e 100644 --- a/tests/unit/drivers/vector/test_pgvector_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_pgvector_vector_store_driver.py @@ -1,25 +1,27 @@ -from typing import Any import uuid -import pytest +from typing import Any from unittest.mock import MagicMock, Mock + +import pytest +from sqlalchemy import create_engine + from griptape.drivers import PgVectorVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver -from sqlalchemy import create_engine class TestPgVectorVectorStoreDriver: connection_string = "postgresql://postgres:postgres@localhost:5432/postgres" table_name = "griptape_vectors" - @pytest.fixture + @pytest.fixture() def embedding_driver(self): return MockEmbeddingDriver() - @pytest.fixture + @pytest.fixture() def mock_engine(self): return MagicMock() - @pytest.fixture + @pytest.fixture() def mock_session(self, mocker): session = MagicMock() mock_session_manager = MagicMock() @@ -30,14 +32,14 @@ def mock_session(self, mocker): def test_initialize_requires_engine_or_connection_string(self, embedding_driver): with pytest.raises(ValueError): - driver = PgVectorVectorStoreDriver(embedding_driver=embedding_driver, table_name=self.table_name) + PgVectorVectorStoreDriver(embedding_driver=embedding_driver, table_name=self.table_name) def test_initialize_accepts_engine(self, embedding_driver): engine: Any = create_engine(self.connection_string) - driver = PgVectorVectorStoreDriver(embedding_driver=embedding_driver, engine=engine, table_name=self.table_name) + PgVectorVectorStoreDriver(embedding_driver=embedding_driver, engine=engine, table_name=self.table_name) def test_initialize_accepts_connection_string(self, embedding_driver): - driver = PgVectorVectorStoreDriver( + PgVectorVectorStoreDriver( embedding_driver=embedding_driver, connection_string=self.connection_string, table_name=self.table_name ) diff --git a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py index 7aea4d411..0726a0c7e 100644 --- a/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py +++ b/tests/unit/drivers/vector/test_pinecone_vector_storage_driver.py @@ -1,19 +1,13 @@ import pytest -from griptape import utils from griptape.artifacts import TextArtifact from griptape.drivers import PineconeVectorStoreDriver from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestPineconeVectorStorageDriver: - """ - This should really be under `unit` but the Pinecone client results - in tests hanging on GitHub. - """ - @pytest.fixture(autouse=True) - def mock_pinecone(self, mocker): + def _mock_pinecone(self, mocker): # Create a fake response fake_query_response = { "matches": [{"id": "foo", "values": [0, 1, 0], "score": 42, "metadata": {"foo": "bar"}}], @@ -25,7 +19,7 @@ def mock_pinecone(self, mocker): mock_client().Index().query.return_value = fake_query_response mock_client().create_index.return_value = None - @pytest.fixture + @pytest.fixture() def driver(self): return PineconeVectorStoreDriver( api_key="foobar", index_name="test", environment="test", embedding_driver=MockEmbeddingDriver() diff --git a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py index 8abfbf4f7..0b22784eb 100644 --- a/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_qdrant_vector_store_driver.py @@ -1,17 +1,19 @@ -import pytest +import uuid from unittest.mock import MagicMock, patch + +import pytest + from griptape.drivers import QdrantVectorStoreDriver -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from griptape.utils import import_optional_dependency -import uuid +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestQdrantVectorStoreDriver: - @pytest.fixture + @pytest.fixture() def embedding_driver(self): return MockEmbeddingDriver() - @pytest.fixture + @pytest.fixture() def mock_engine(self): return MagicMock() diff --git a/tests/unit/drivers/vector/test_redis_vector_store_driver.py b/tests/unit/drivers/vector/test_redis_vector_store_driver.py index 18759a2d7..2f74b9279 100644 --- a/tests/unit/drivers/vector/test_redis_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_redis_vector_store_driver.py @@ -1,7 +1,9 @@ from unittest.mock import MagicMock + import pytest -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver + from griptape.drivers import RedisVectorStoreDriver +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestRedisVectorStorageDriver: @@ -9,12 +11,12 @@ class TestRedisVectorStorageDriver: def mock_client(self, mocker): return mocker.patch("redis.Redis").return_value - @pytest.fixture + @pytest.fixture() def mock_keys(self, mock_client): mock_client.keys.return_value = [b"some_vector_id"] return mock_client.keys - @pytest.fixture + @pytest.fixture() def mock_hgetall(self, mock_client): mock_client.hgetall.return_value = { b"vector": b"\x00\x00\x80?\x00\x00\x00@\x00\x00@@", @@ -22,13 +24,13 @@ def mock_hgetall(self, mock_client): } return mock_client.hgetall - @pytest.fixture + @pytest.fixture() def driver(self): return RedisVectorStoreDriver( host="localhost", port=6379, index="test_index", db=0, embedding_driver=MockEmbeddingDriver() ) - @pytest.fixture + @pytest.fixture() def mock_search(self, mock_client): mock_client.ft.return_value.search.return_value.docs = [ MagicMock( diff --git a/tests/unit/drivers/web_scraper/test_markdownify_web_scraper_driver.py b/tests/unit/drivers/web_scraper/test_markdownify_web_scraper_driver.py index 33500839f..dbdafa98f 100644 --- a/tests/unit/drivers/web_scraper/test_markdownify_web_scraper_driver.py +++ b/tests/unit/drivers/web_scraper/test_markdownify_web_scraper_driver.py @@ -1,4 +1,5 @@ from textwrap import dedent + import pytest from griptape.drivers.web_scraper.markdownify_web_scraper_driver import MarkdownifyWebScraperDriver @@ -15,13 +16,13 @@ def mock_content(self, mock_playwright): mock_content.return_value = 'foobar' return mock_content - @pytest.fixture + @pytest.fixture() def web_scraper(self): return MarkdownifyWebScraperDriver() def test_scrape_url(self, web_scraper): artifact = web_scraper.scrape_url("https://example.com/") - assert "[foobar](foobar.com)" == artifact.value + assert artifact.value == "[foobar](foobar.com)" def test_scrape_url_whitespace(self, web_scraper, mock_content): mock_content.return_value = dedent( @@ -46,35 +47,35 @@ def test_scrape_url_whitespace(self, web_scraper, mock_content): """ ) artifact = web_scraper.scrape_url("https://example.com/") - assert "foo\n---\n\n* bar:\n + baz\n + baz\n\n + baz" == artifact.value + assert artifact.value == "foo\n---\n\n* bar:\n + baz\n + baz\n\n + baz" def test_scrape_url_no_excludes(self): web_scraper = MarkdownifyWebScraperDriver(exclude_tags=[], exclude_classes=[], exclude_ids=[]) artifact = web_scraper.scrape_url("https://example.com/") - assert "[foobar](foobar.com)" == artifact.value + assert artifact.value == "[foobar](foobar.com)" def test_scrape_url_exclude_links(self): web_scraper = MarkdownifyWebScraperDriver(include_links=False) artifact = web_scraper.scrape_url("https://example.com/") - assert "foobar" == artifact.value + assert artifact.value == "foobar" def test_scrape_url_exclude_tags(self, mock_content): mock_content.return_value = "powwow" web_scraper = MarkdownifyWebScraperDriver(exclude_tags=["wow"], exclude_classes=[], exclude_ids=[]) artifact = web_scraper.scrape_url("https://example.com/") - assert "pow" == artifact.value + assert artifact.value == "pow" def test_scrape_url_exclude_classes(self, mock_content): mock_content.return_value = 'powwow' web_scraper = MarkdownifyWebScraperDriver(exclude_tags=[], exclude_classes=["now"], exclude_ids=[]) artifact = web_scraper.scrape_url("https://example.com/") - assert "pow" == artifact.value + assert artifact.value == "pow" def test_scrape_url_exclude_ids(self, mock_content): mock_content.return_value = 'powwow' web_scraper = MarkdownifyWebScraperDriver(exclude_tags=[], exclude_classes=[], exclude_ids=["cow"]) artifact = web_scraper.scrape_url("https://example.com/") - assert "pow" == artifact.value + assert artifact.value == "pow" def test_scrape_url_raises_on_empty_string_from_playwright(self, web_scraper, mock_content): mock_content.return_value = "" diff --git a/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py b/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py index 569800c6a..95e5a2880 100644 --- a/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py +++ b/tests/unit/drivers/web_scraper/test_proxy_web_scraper_driver.py @@ -1,7 +1,7 @@ import pytest -from griptape.drivers import ProxyWebScraperDriver from griptape.artifacts import TextArtifact +from griptape.drivers import ProxyWebScraperDriver class TestProxyWebScraperDriver: @@ -11,11 +11,11 @@ def mock_client(self, mocker): mock_response.text = "test_scrape" return mocker.patch("requests.get", return_value=mock_response) - @pytest.fixture + @pytest.fixture() def mock_client_error(self, mocker): return mocker.patch("requests.get", side_effect=Exception("test_error")) - @pytest.fixture + @pytest.fixture() def web_scraper(self, mocker): return ProxyWebScraperDriver( proxies={"http": "http://localhost:8080", "https": "http://localhost:8080"}, @@ -26,7 +26,7 @@ def test_scrape_url(self, web_scraper, mock_client): output = web_scraper.scrape_url("https://example.com/") mock_client.assert_called_with("https://example.com/", proxies=web_scraper.proxies, test_param="test_param") assert isinstance(output, TextArtifact) - assert "test_scrape" == output.value + assert output.value == "test_scrape" def test_scrape_url_error(self, web_scraper, mock_client_error): with pytest.raises(Exception, match="test_error"): diff --git a/tests/unit/drivers/web_scraper/test_trafilatura_web_scraper_driver.py b/tests/unit/drivers/web_scraper/test_trafilatura_web_scraper_driver.py index f2ea56666..53ddf4500 100644 --- a/tests/unit/drivers/web_scraper/test_trafilatura_web_scraper_driver.py +++ b/tests/unit/drivers/web_scraper/test_trafilatura_web_scraper_driver.py @@ -5,7 +5,7 @@ class TestTrafilaturaWebScraperDriver: @pytest.fixture(autouse=True) - def mock_fetch_url(self, mocker): + def _mock_fetch_url(self, mocker): # Through trial and error, I've found that include_links in trafilatura's extract does not work # if the body of the page is not long enough, which is why I'm adding an arbitrary number of # characters to the body. @@ -13,7 +13,7 @@ def mock_fetch_url(self, mocker): "trafilatura.fetch_url" ).return_value = f'{"x"*243}foobar' - @pytest.fixture + @pytest.fixture() def web_scraper(self): return TrafilaturaWebScraperDriver(include_links=True) diff --git a/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py b/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py index fcacc274c..3d0a782eb 100644 --- a/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py +++ b/tests/unit/drivers/web_search/test_duck_duck_go_web_search_driver.py @@ -1,11 +1,13 @@ -import pytest import json -from griptape.drivers import DuckDuckGoWebSearchDriver + +import pytest + from griptape.artifacts import ListArtifact +from griptape.drivers import DuckDuckGoWebSearchDriver class TestDuckDuckGoWebSearchDriver: - @pytest.fixture + @pytest.fixture() def driver(self, mocker): mock_response = [ {"title": "foo", "href": "bar", "body": "baz"}, @@ -16,7 +18,7 @@ def driver(self, mocker): return DuckDuckGoWebSearchDriver() - @pytest.fixture + @pytest.fixture() def driver_with_error(self, mocker): mocker.patch("duckduckgo_search.DDGS.text", side_effect=Exception("test_error")) diff --git a/tests/unit/drivers/web_search/test_google_web_search_driver.py b/tests/unit/drivers/web_search/test_google_web_search_driver.py index 9ecb92f46..3809532de 100644 --- a/tests/unit/drivers/web_search/test_google_web_search_driver.py +++ b/tests/unit/drivers/web_search/test_google_web_search_driver.py @@ -1,13 +1,13 @@ -from pytest import fixture -import pytest -from griptape.drivers import GoogleWebSearchDriver -from griptape.artifacts import ErrorArtifact import json + +import pytest from pytest_mock import MockerFixture +from griptape.drivers import GoogleWebSearchDriver + class TestGoogleWebSearchDriver: - @fixture + @pytest.fixture() def driver(self, mocker: MockerFixture): mock_response = mocker.Mock() mocker.patch.object( @@ -19,7 +19,7 @@ def driver(self, mocker: MockerFixture): return GoogleWebSearchDriver(api_key="test", search_id="test") - @fixture + @pytest.fixture() def driver_with_error(self, mocker: MockerFixture): mock_response = mocker.Mock() mock_response.status_code = 500 diff --git a/tests/unit/engines/extraction/test_csv_extraction_engine.py b/tests/unit/engines/extraction/test_csv_extraction_engine.py index ded595d59..f69d8a0ba 100644 --- a/tests/unit/engines/extraction/test_csv_extraction_engine.py +++ b/tests/unit/engines/extraction/test_csv_extraction_engine.py @@ -1,10 +1,11 @@ import pytest + from griptape.engines import CsvExtractionEngine from tests.mocks.mock_prompt_driver import MockPromptDriver class TestCsvExtractionEngine: - @pytest.fixture + @pytest.fixture() def engine(self): return CsvExtractionEngine(prompt_driver=MockPromptDriver()) diff --git a/tests/unit/engines/extraction/test_json_extraction_engine.py b/tests/unit/engines/extraction/test_json_extraction_engine.py index 797c5de7a..d95adbb43 100644 --- a/tests/unit/engines/extraction/test_json_extraction_engine.py +++ b/tests/unit/engines/extraction/test_json_extraction_engine.py @@ -1,12 +1,13 @@ import pytest from schema import Schema + from griptape.artifacts import ErrorArtifact from griptape.engines import JsonExtractionEngine from tests.mocks.mock_prompt_driver import MockPromptDriver class TestJsonExtractionEngine: - @pytest.fixture + @pytest.fixture() def engine(self): return JsonExtractionEngine( prompt_driver=MockPromptDriver( diff --git a/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py index e5ba50a5b..385cf0c04 100644 --- a/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py +++ b/tests/unit/engines/rag/modules/generation/test_footnote_prompt_response_rag_module.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts import TextArtifact from griptape.common import Reference from griptape.engines.rag import RagContext @@ -7,7 +8,7 @@ class TestFootnotePromptResponseRagModule: - @pytest.fixture + @pytest.fixture() def module(self): return FootnotePromptResponseRagModule(prompt_driver=MockPromptDriver()) diff --git a/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py index f262d6d06..2f8a912e2 100644 --- a/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py +++ b/tests/unit/engines/rag/modules/generation/test_prompt_response_rag_module.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts import TextArtifact from griptape.engines.rag import RagContext from griptape.engines.rag.modules import PromptResponseRagModule @@ -6,7 +7,7 @@ class TestPromptResponseRagModule: - @pytest.fixture + @pytest.fixture() def module(self): return PromptResponseRagModule(prompt_driver=MockPromptDriver()) diff --git a/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py index 2750257f4..bc85cf266 100644 --- a/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py +++ b/tests/unit/engines/rag/modules/generation/test_rulesets_before_response_rag_module.py @@ -1,6 +1,6 @@ from griptape.engines.rag import RagContext from griptape.engines.rag.modules import RulesetsBeforeResponseRagModule -from griptape.rules import Ruleset, Rule +from griptape.rules import Rule, Ruleset class TestRulesetsBeforeResponseRagModule: diff --git a/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py b/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py index 6488d650e..ae4410b2c 100644 --- a/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py +++ b/tests/unit/engines/rag/modules/generation/test_text_chunks_response_rag_module.py @@ -1,11 +1,12 @@ import pytest + from griptape.artifacts import TextArtifact from griptape.engines.rag import RagContext from griptape.engines.rag.modules import TextChunksResponseRagModule class TestTextChunksResponseRagModule: - @pytest.fixture + @pytest.fixture() def module(self): return TextChunksResponseRagModule() diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py index fa3bfecb2..dda6e89e7 100644 --- a/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py +++ b/tests/unit/engines/rag/modules/retrieval/test_text_chunks_rerank_rag_module.py @@ -1,5 +1,6 @@ import pytest from cohere import RerankResponseResultsItem, RerankResponseResultsItemDocument + from griptape.artifacts import TextArtifact from griptape.drivers import CohereRerankDriver from griptape.engines.rag import RagContext @@ -7,7 +8,7 @@ class TestTextChunksRerankRagModule: - @pytest.fixture + @pytest.fixture() def mock_client(self, mocker): mock_client = mocker.patch("cohere.Client").return_value mock_client.rerank.return_value.results = [ diff --git a/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py b/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py index 7c69f674a..69e334c7f 100644 --- a/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py +++ b/tests/unit/engines/rag/modules/retrieval/test_text_loader_retrieval_rag_module.py @@ -11,7 +11,7 @@ class TestTextLoaderRetrievalRagModule: @pytest.fixture(autouse=True) - def mock_trafilatura_fetch_url(self, mocker): + def _mock_trafilatura_fetch_url(self, mocker): mocker.patch("trafilatura.fetch_url", return_value="foobar") def test_run(self): diff --git a/tests/unit/engines/rag/test_rag_engine.py b/tests/unit/engines/rag/test_rag_engine.py index a39c0c2f1..c3d728bb3 100644 --- a/tests/unit/engines/rag/test_rag_engine.py +++ b/tests/unit/engines/rag/test_rag_engine.py @@ -1,14 +1,15 @@ import pytest + from griptape.drivers import LocalVectorStoreDriver -from griptape.engines.rag import RagEngine, RagContext -from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule -from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage +from griptape.engines.rag import RagContext, RagEngine +from griptape.engines.rag.modules import PromptResponseRagModule, VectorStoreRetrievalRagModule +from griptape.engines.rag.stages import ResponseRagStage, RetrievalRagStage from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_prompt_driver import MockPromptDriver class TestRagEngine: - @pytest.fixture + @pytest.fixture() def engine(self): return RagEngine( retrieval_stage=RetrievalRagStage( diff --git a/tests/unit/engines/summary/test_prompt_summary_engine.py b/tests/unit/engines/summary/test_prompt_summary_engine.py index 34c6e3563..e826a2b4d 100644 --- a/tests/unit/engines/summary/test_prompt_summary_engine.py +++ b/tests/unit/engines/summary/test_prompt_summary_engine.py @@ -1,13 +1,15 @@ +import os + import pytest -from griptape.artifacts import TextArtifact, ListArtifact -from griptape.engines import PromptSummaryEngine + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.common import PromptStack +from griptape.engines import PromptSummaryEngine from tests.mocks.mock_prompt_driver import MockPromptDriver -import os class TestPromptSummaryEngine: - @pytest.fixture + @pytest.fixture() def engine(self): return PromptSummaryEngine(prompt_driver=MockPromptDriver()) diff --git a/tests/unit/events/test_base_event.py b/tests/unit/events/test_base_event.py index 595c90f1f..778f7c096 100644 --- a/tests/unit/events/test_base_event.py +++ b/tests/unit/events/test_base_event.py @@ -1,17 +1,19 @@ import time + import pytest + from griptape.artifacts.base_artifact import BaseArtifact from griptape.events import ( - StartPromptEvent, + BaseEvent, + CompletionChunkEvent, + FinishActionsSubtaskEvent, FinishPromptEvent, - StartTaskEvent, + FinishStructureRunEvent, FinishTaskEvent, StartActionsSubtaskEvent, - FinishActionsSubtaskEvent, - CompletionChunkEvent, + StartPromptEvent, StartStructureRunEvent, - FinishStructureRunEvent, - BaseEvent, + StartTaskEvent, ) from tests.mocks.mock_event import MockEvent diff --git a/tests/unit/events/test_completion_chunk_event.py b/tests/unit/events/test_completion_chunk_event.py index aa9618a53..943ea483f 100644 --- a/tests/unit/events/test_completion_chunk_event.py +++ b/tests/unit/events/test_completion_chunk_event.py @@ -1,9 +1,10 @@ import pytest + from griptape.events import CompletionChunkEvent class TestCompletionChunkEvent: - @pytest.fixture + @pytest.fixture() def completion_chunk_event(self): return CompletionChunkEvent(token="foo bar") diff --git a/tests/unit/events/test_event_listener.py b/tests/unit/events/test_event_listener.py index 2f32837e0..a79d2b6ea 100644 --- a/tests/unit/events/test_event_listener.py +++ b/tests/unit/events/test_event_listener.py @@ -1,27 +1,29 @@ from unittest.mock import Mock + import pytest -from griptape.events.base_event import BaseEvent -from griptape.structures import Pipeline -from griptape.tasks import ToolkitTask, ActionsSubtask + from griptape.events import ( - StartTaskEvent, + CompletionChunkEvent, + EventListener, + FinishActionsSubtaskEvent, + FinishPromptEvent, + FinishStructureRunEvent, FinishTaskEvent, StartActionsSubtaskEvent, - FinishActionsSubtaskEvent, StartPromptEvent, - FinishPromptEvent, StartStructureRunEvent, - FinishStructureRunEvent, - CompletionChunkEvent, - EventListener, + StartTaskEvent, ) +from griptape.events.base_event import BaseEvent +from griptape.structures import Pipeline +from griptape.tasks import ActionsSubtask, ToolkitTask +from tests.mocks.mock_event import MockEvent from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tool.tool import MockTool -from tests.mocks.mock_event import MockEvent class TestEventListener: - @pytest.fixture + @pytest.fixture() def pipeline(self): task = ToolkitTask("test", tools=[MockTool(name="Tool1")]) @@ -107,7 +109,7 @@ def test_publish_event(self): mock_event_listener_driver = Mock() mock_event_listener_driver.try_publish_event_payload.return_value = None - def event_handler(_: BaseEvent): + def event_handler(_: BaseEvent) -> None: return None mock_event = MockEvent() diff --git a/tests/unit/events/test_finish_actions_subtask_event.py b/tests/unit/events/test_finish_actions_subtask_event.py index 14d7cbdde..5e2a0807a 100644 --- a/tests/unit/events/test_finish_actions_subtask_event.py +++ b/tests/unit/events/test_finish_actions_subtask_event.py @@ -1,4 +1,5 @@ import pytest + from griptape.events import FinishActionsSubtaskEvent from griptape.structures import Agent from griptape.tasks import ActionsSubtask, ToolkitTask @@ -7,7 +8,7 @@ class TestFinishActionsSubtaskEvent: - @pytest.fixture + @pytest.fixture() def finish_subtask_event(self): valid_input = ( "Thought: need to test\n" diff --git a/tests/unit/events/test_finish_prompt_event.py b/tests/unit/events/test_finish_prompt_event.py index 7443fce0c..397efe8a0 100644 --- a/tests/unit/events/test_finish_prompt_event.py +++ b/tests/unit/events/test_finish_prompt_event.py @@ -1,9 +1,10 @@ import pytest + from griptape.events import FinishPromptEvent class TestFinishPromptEvent: - @pytest.fixture + @pytest.fixture() def finish_prompt_event(self): return FinishPromptEvent(input_token_count=321, output_token_count=123, result="foo bar", model="foo bar") diff --git a/tests/unit/events/test_finish_structure_run_event.py b/tests/unit/events/test_finish_structure_run_event.py index 0e9e61f4f..9c0961314 100644 --- a/tests/unit/events/test_finish_structure_run_event.py +++ b/tests/unit/events/test_finish_structure_run_event.py @@ -5,7 +5,7 @@ class TestFinishStructureRunEvent: - @pytest.fixture + @pytest.fixture() def finish_structure_run_event(self): return FinishStructureRunEvent( structure_id="fizz", diff --git a/tests/unit/events/test_finish_task_event.py b/tests/unit/events/test_finish_task_event.py index 40e71c9ea..df1d6d42a 100644 --- a/tests/unit/events/test_finish_task_event.py +++ b/tests/unit/events/test_finish_task_event.py @@ -1,12 +1,13 @@ import pytest -from griptape.structures import Agent + from griptape.events import FinishTaskEvent +from griptape.structures import Agent from griptape.tasks import PromptTask from tests.mocks.mock_prompt_driver import MockPromptDriver class TestFinishTaskEvent: - @pytest.fixture + @pytest.fixture() def finish_task_event(self): task = PromptTask() agent = Agent(prompt_driver=MockPromptDriver()) diff --git a/tests/unit/events/test_start_actions_subtask_event.py b/tests/unit/events/test_start_actions_subtask_event.py index d8b63de22..8b628057c 100644 --- a/tests/unit/events/test_start_actions_subtask_event.py +++ b/tests/unit/events/test_start_actions_subtask_event.py @@ -1,4 +1,5 @@ import pytest + from griptape.events import StartActionsSubtaskEvent from griptape.structures import Agent from griptape.tasks import ActionsSubtask, ToolkitTask @@ -7,7 +8,7 @@ class TestStartActionsSubtaskEvent: - @pytest.fixture + @pytest.fixture() def start_subtask_event(self): valid_input = ( "Thought: need to test\n" diff --git a/tests/unit/events/test_start_prompt_event.py b/tests/unit/events/test_start_prompt_event.py index 4ef08ec5c..2d7e9368f 100644 --- a/tests/unit/events/test_start_prompt_event.py +++ b/tests/unit/events/test_start_prompt_event.py @@ -1,10 +1,11 @@ import pytest -from griptape.events import StartPromptEvent + from griptape.common import PromptStack +from griptape.events import StartPromptEvent class TestStartPromptEvent: - @pytest.fixture + @pytest.fixture() def start_prompt_event(self): prompt_stack = PromptStack() prompt_stack.add_user_message("foo") diff --git a/tests/unit/events/test_start_structure_run_event.py b/tests/unit/events/test_start_structure_run_event.py index c2f1b923d..221f1a544 100644 --- a/tests/unit/events/test_start_structure_run_event.py +++ b/tests/unit/events/test_start_structure_run_event.py @@ -1,10 +1,11 @@ import pytest + from griptape.artifacts.text_artifact import TextArtifact from griptape.events import StartStructureRunEvent class TestStartStructureRunEvent: - @pytest.fixture + @pytest.fixture() def start_structure_run_event(self): return StartStructureRunEvent( structure_id="fizz", input_task_input=TextArtifact("foo"), input_task_output=TextArtifact("bar") diff --git a/tests/unit/events/test_start_task_event.py b/tests/unit/events/test_start_task_event.py index f4d243421..ea027f147 100644 --- a/tests/unit/events/test_start_task_event.py +++ b/tests/unit/events/test_start_task_event.py @@ -1,4 +1,5 @@ import pytest + from griptape.events import StartTaskEvent from griptape.structures import Agent from griptape.tasks import PromptTask @@ -6,7 +7,7 @@ class TestStartTaskEvent: - @pytest.fixture + @pytest.fixture() def start_task_event(self): task = PromptTask() agent = Agent(prompt_driver=MockPromptDriver()) diff --git a/tests/unit/loaders/conftest.py b/tests/unit/loaders/conftest.py index e1823a154..494916be6 100644 --- a/tests/unit/loaders/conftest.py +++ b/tests/unit/loaders/conftest.py @@ -4,7 +4,7 @@ import pytest -@pytest.fixture +@pytest.fixture() def path_from_resource_path(): def create_source(resource_path: str) -> Path: return Path(os.path.join(os.path.abspath(os.path.dirname(__file__)), "../../resources", resource_path)) @@ -12,7 +12,7 @@ def create_source(resource_path: str) -> Path: return create_source -@pytest.fixture +@pytest.fixture() def bytes_from_resource_path(path_from_resource_path): def create_source(resource_path: str) -> bytes: with open(path_from_resource_path(resource_path), "rb") as f: @@ -21,7 +21,7 @@ def create_source(resource_path: str) -> bytes: return create_source -@pytest.fixture +@pytest.fixture() def str_from_resource_path(path_from_resource_path): def test_csv_str(resource_path: str) -> str: with open(path_from_resource_path(resource_path)) as f: diff --git a/tests/unit/loaders/test_audio_loader.py b/tests/unit/loaders/test_audio_loader.py index b7946da03..473fd0d9e 100644 --- a/tests/unit/loaders/test_audio_loader.py +++ b/tests/unit/loaders/test_audio_loader.py @@ -5,15 +5,15 @@ class TestAudioLoader: - @pytest.fixture + @pytest.fixture() def loader(self): return AudioLoader() - @pytest.fixture + @pytest.fixture() def create_source(self, bytes_from_resource_path): return bytes_from_resource_path - @pytest.mark.parametrize("resource_path,suffix,mime_type", [("sentences.wav", ".wav", "audio/wav")]) + @pytest.mark.parametrize(("resource_path", "suffix", "mime_type"), [("sentences.wav", ".wav", "audio/wav")]) def test_load(self, resource_path, suffix, mime_type, loader, create_source): source = create_source(resource_path) @@ -32,8 +32,7 @@ def test_load_collection(self, create_source, loader): assert len(collection) == len(resource_paths) - keys = {loader.to_key(source) for source in sources} - for key in collection.keys(): + for key in collection: artifact = collection[key] assert isinstance(artifact, AudioArtifact) assert artifact.name.endswith(".wav") diff --git a/tests/unit/loaders/test_blob_loader.py b/tests/unit/loaders/test_blob_loader.py index f2b462726..4812e669c 100644 --- a/tests/unit/loaders/test_blob_loader.py +++ b/tests/unit/loaders/test_blob_loader.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts import BlobArtifact from griptape.loaders import BlobLoader diff --git a/tests/unit/loaders/test_csv_loader.py b/tests/unit/loaders/test_csv_loader.py index 579146ba2..a747afff7 100644 --- a/tests/unit/loaders/test_csv_loader.py +++ b/tests/unit/loaders/test_csv_loader.py @@ -1,4 +1,5 @@ import pytest + from griptape.loaders.csv_loader import CsvLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -12,7 +13,7 @@ def loader(self, request): else: return CsvLoader(embedding_driver=MockEmbeddingDriver(), encoding=encoding) - @pytest.fixture + @pytest.fixture() def loader_with_pipe_delimiter(self): return CsvLoader(embedding_driver=MockEmbeddingDriver(), delimiter="|") diff --git a/tests/unit/loaders/test_dataframe_loader.py b/tests/unit/loaders/test_dataframe_loader.py index 536555558..5c2a57ed6 100644 --- a/tests/unit/loaders/test_dataframe_loader.py +++ b/tests/unit/loaders/test_dataframe_loader.py @@ -1,13 +1,14 @@ import os + import pandas as pd import pytest -from griptape import utils + from griptape.loaders.dataframe_loader import DataFrameLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestDataFrameLoader: - @pytest.fixture + @pytest.fixture() def loader(self): return DataFrameLoader(embedding_driver=MockEmbeddingDriver()) diff --git a/tests/unit/loaders/test_email_loader.py b/tests/unit/loaders/test_email_loader.py index ef69b8348..f1e057453 100644 --- a/tests/unit/loaders/test_email_loader.py +++ b/tests/unit/loaders/test_email_loader.py @@ -1,12 +1,14 @@ from __future__ import annotations +import email from email import message -from griptape.artifacts import ErrorArtifact, ListArtifact -from griptape.loaders import EmailLoader from typing import Optional -import email + import pytest +from griptape.artifacts import ErrorArtifact, ListArtifact +from griptape.loaders import EmailLoader + class TestEmailLoader: @pytest.fixture(autouse=True) @@ -15,7 +17,7 @@ def mock_imap_connection(self, mocker): mock_imap_connection.__enter__.return_value = mock_imap_connection return mock_imap_connection - @pytest.fixture + @pytest.fixture() def mock_login(self, mock_imap_connection): return mock_imap_connection.login @@ -25,7 +27,7 @@ def mock_select(self, mock_imap_connection): mock_select.return_value = to_select_response("OK", 1) return mock_select - @pytest.fixture + @pytest.fixture() def mock_search(self, mock_imap_connection): return mock_imap_connection.search @@ -35,7 +37,7 @@ def mock_fetch(self, mock_imap_connection): mock_fetch.return_value = to_fetch_message("message", "text/plain") return mock_fetch - @pytest.fixture + @pytest.fixture() def loader(self): return EmailLoader(imap_url="an.email.server.hostname", username="username", password="password") diff --git a/tests/unit/loaders/test_image_loader.py b/tests/unit/loaders/test_image_loader.py index 2a90d6b5d..eca4cbccc 100644 --- a/tests/unit/loaders/test_image_loader.py +++ b/tests/unit/loaders/test_image_loader.py @@ -5,20 +5,20 @@ class TestImageLoader: - @pytest.fixture + @pytest.fixture() def loader(self): return ImageLoader() - @pytest.fixture + @pytest.fixture() def png_loader(self): return ImageLoader(format="png") - @pytest.fixture + @pytest.fixture() def create_source(self, bytes_from_resource_path): return bytes_from_resource_path @pytest.mark.parametrize( - "resource_path,suffix,mime_type", + ("resource_path", "suffix", "mime_type"), [ ("small.png", ".png", "image/png"), ("small.jpg", ".jpeg", "image/jpeg"), diff --git a/tests/unit/loaders/test_pdf_loader.py b/tests/unit/loaders/test_pdf_loader.py index 0ab78b8b6..3f4f7848e 100644 --- a/tests/unit/loaders/test_pdf_loader.py +++ b/tests/unit/loaders/test_pdf_loader.py @@ -1,8 +1,5 @@ -import os -from pathlib import Path -from typing import IO import pytest -from griptape import utils + from griptape.loaders import PdfLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -10,11 +7,11 @@ class TestPdfLoader: - @pytest.fixture + @pytest.fixture() def loader(self): return PdfLoader(max_tokens=MAX_TOKENS, embedding_driver=MockEmbeddingDriver()) - @pytest.fixture + @pytest.fixture() def create_source(self, bytes_from_resource_path): return bytes_from_resource_path diff --git a/tests/unit/loaders/test_sql_loader.py b/tests/unit/loaders/test_sql_loader.py index 8541e4fb8..fbfa6d4fa 100644 --- a/tests/unit/loaders/test_sql_loader.py +++ b/tests/unit/loaders/test_sql_loader.py @@ -1,5 +1,6 @@ import pytest from sqlalchemy.pool import StaticPool + from griptape.drivers import SqlDriver from griptape.loaders import SqlLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -8,7 +9,7 @@ class TestSqlLoader: - @pytest.fixture + @pytest.fixture() def loader(self): sql_loader = SqlLoader( sql_driver=SqlDriver( diff --git a/tests/unit/loaders/test_text_loader.py b/tests/unit/loaders/test_text_loader.py index 0c59df12f..07527f9e6 100644 --- a/tests/unit/loaders/test_text_loader.py +++ b/tests/unit/loaders/test_text_loader.py @@ -1,4 +1,5 @@ import pytest + from griptape.loaders.text_loader import TextLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver diff --git a/tests/unit/loaders/test_web_loader.py b/tests/unit/loaders/test_web_loader.py index e26573539..f264ce667 100644 --- a/tests/unit/loaders/test_web_loader.py +++ b/tests/unit/loaders/test_web_loader.py @@ -1,4 +1,5 @@ import pytest + from griptape.artifacts.error_artifact import ErrorArtifact from griptape.loaders import WebLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -8,10 +9,10 @@ class TestWebLoader: @pytest.fixture(autouse=True) - def mock_trafilatura_fetch_url(self, mocker): + def _mock_trafilatura_fetch_url(self, mocker): mocker.patch("trafilatura.fetch_url", return_value="foobar") - @pytest.fixture + @pytest.fixture() def loader(self): return WebLoader(max_tokens=MAX_TOKENS, embedding_driver=MockEmbeddingDriver()) diff --git a/tests/unit/memory/meta/test_action_subtask_meta_entry.py b/tests/unit/memory/meta/test_action_subtask_meta_entry.py index f5da6ee01..0a51e7227 100644 --- a/tests/unit/memory/meta/test_action_subtask_meta_entry.py +++ b/tests/unit/memory/meta/test_action_subtask_meta_entry.py @@ -1,9 +1,10 @@ import pytest + from griptape.memory.meta import ActionSubtaskMetaEntry class TestActionSubtaskMetaEntry: - @pytest.fixture + @pytest.fixture() def entry(self): return ActionSubtaskMetaEntry(thought="foo", actions="[]", answer="baz") diff --git a/tests/unit/memory/meta/test_meta_memory.py b/tests/unit/memory/meta/test_meta_memory.py index bbdacf5b4..5a1249529 100644 --- a/tests/unit/memory/meta/test_meta_memory.py +++ b/tests/unit/memory/meta/test_meta_memory.py @@ -1,9 +1,10 @@ import pytest -from griptape.memory.meta import MetaMemory, ActionSubtaskMetaEntry + +from griptape.memory.meta import ActionSubtaskMetaEntry, MetaMemory class TestMetaMemory: - @pytest.fixture + @pytest.fixture() def memory(self): return MetaMemory() diff --git a/tests/unit/memory/structure/test_conversation_memory.py b/tests/unit/memory/structure/test_conversation_memory.py index 613d4b1fe..2ffd7b8cb 100644 --- a/tests/unit/memory/structure/test_conversation_memory.py +++ b/tests/unit/memory/structure/test_conversation_memory.py @@ -1,12 +1,12 @@ import json -from griptape.structures import Agent + +from griptape.artifacts import TextArtifact from griptape.common import PromptStack -from griptape.memory.structure import ConversationMemory, Run, BaseConversationMemory -from griptape.structures import Pipeline +from griptape.memory.structure import BaseConversationMemory, ConversationMemory, Run +from griptape.structures import Agent, Pipeline +from griptape.tasks import PromptTask from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tokenizer import MockTokenizer -from griptape.tasks import PromptTask -from griptape.artifacts import TextArtifact class TestConversationMemory: diff --git a/tests/unit/memory/structure/test_summary_conversation_memory.py b/tests/unit/memory/structure/test_summary_conversation_memory.py index e625ac6c6..4396c7b23 100644 --- a/tests/unit/memory/structure/test_summary_conversation_memory.py +++ b/tests/unit/memory/structure/test_summary_conversation_memory.py @@ -1,9 +1,8 @@ import json - +from griptape.artifacts import TextArtifact from griptape.memory.structure import Run, SummaryConversationMemory from griptape.structures import Pipeline -from griptape.artifacts import TextArtifact from griptape.tasks import PromptTask from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_structure_config import MockStructureConfig diff --git a/tests/unit/memory/tool/storage/test_blob_artifact_storage.py b/tests/unit/memory/tool/storage/test_blob_artifact_storage.py index dd42b6bc2..c7f2cfcbd 100644 --- a/tests/unit/memory/tool/storage/test_blob_artifact_storage.py +++ b/tests/unit/memory/tool/storage/test_blob_artifact_storage.py @@ -1,10 +1,11 @@ import pytest + from griptape.artifacts import BlobArtifact, TextArtifact from griptape.memory.task.storage import BlobArtifactStorage class TestBlobArtifactStorage: - @pytest.fixture + @pytest.fixture() def storage(self): return BlobArtifactStorage() diff --git a/tests/unit/memory/tool/storage/test_text_artifact_storage.py b/tests/unit/memory/tool/storage/test_text_artifact_storage.py index 706a80f0c..64f44c581 100644 --- a/tests/unit/memory/tool/storage/test_text_artifact_storage.py +++ b/tests/unit/memory/tool/storage/test_text_artifact_storage.py @@ -1,10 +1,11 @@ import pytest + from griptape.artifacts import BlobArtifact, TextArtifact from tests.utils import defaults class TestTextArtifactStorage: - @pytest.fixture + @pytest.fixture() def storage(self): return defaults.text_tool_artifact_storage() diff --git a/tests/unit/memory/tool/test_task_memory.py b/tests/unit/memory/tool/test_task_memory.py index fc1cf75c7..53e4703a6 100644 --- a/tests/unit/memory/tool/test_task_memory.py +++ b/tests/unit/memory/tool/test_task_memory.py @@ -1,6 +1,6 @@ import pytest -from griptape.artifacts import CsvRowArtifact, BlobArtifact, ErrorArtifact, InfoArtifact -from griptape.artifacts import TextArtifact, ListArtifact + +from griptape.artifacts import BlobArtifact, CsvRowArtifact, ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.memory import TaskMemory from griptape.memory.task.storage import BlobArtifactStorage, TextArtifactStorage from griptape.structures import Agent @@ -11,10 +11,10 @@ class TestTaskMemory: @pytest.fixture(autouse=True) - def mock_griptape(self, mocker): + def _mock_griptape(self, mocker): mocker.patch("griptape.engines.CsvExtractionEngine.extract", return_value=[CsvRowArtifact({"foo": "bar"})]) - @pytest.fixture + @pytest.fixture() def memory(self): return defaults.text_task_memory("MyMemory") diff --git a/tests/unit/mixins/test_activity_mixin.py b/tests/unit/mixins/test_activity_mixin.py index 45db7cc7f..91e0c3a67 100644 --- a/tests/unit/mixins/test_activity_mixin.py +++ b/tests/unit/mixins/test_activity_mixin.py @@ -1,10 +1,11 @@ import pytest -from schema import Schema, Literal, Optional +from schema import Literal, Optional, Schema + from tests.mocks.mock_tool.tool import MockTool class TestActivityMixin: - @pytest.fixture + @pytest.fixture() def tool(self): return MockTool(test_field="hello", test_int=5) diff --git a/tests/unit/mixins/test_image_artifact_file_output_mixin.py b/tests/unit/mixins/test_image_artifact_file_output_mixin.py index 69a2f1d71..03c44e081 100644 --- a/tests/unit/mixins/test_image_artifact_file_output_mixin.py +++ b/tests/unit/mixins/test_image_artifact_file_output_mixin.py @@ -19,7 +19,7 @@ def test_output_file(self): artifact = ImageArtifact(name="test.png", value=b"test", height=1, width=1, format="png") class Test(BlobArtifactFileOutputMixin): - def run(self): + def run(self) -> None: self._write_to_file(artifact) outfile = os.path.join(tempfile.gettempdir(), artifact.name) @@ -34,7 +34,7 @@ def test_output_dir(self): artifact = ImageArtifact(name="test.png", value=b"test", height=1, width=1, format="png") class Test(BlobArtifactFileOutputMixin): - def run(self): + def run(self) -> None: self._write_to_file(artifact) outdir = tempfile.gettempdir() diff --git a/tests/unit/mixins/test_seriliazable_mixin.py b/tests/unit/mixins/test_seriliazable_mixin.py index 1704000e3..afb3d1eb4 100644 --- a/tests/unit/mixins/test_seriliazable_mixin.py +++ b/tests/unit/mixins/test_seriliazable_mixin.py @@ -1,11 +1,13 @@ import json + import pytest + +from griptape.artifacts import BaseArtifact, TextArtifact from griptape.drivers import OpenAiChatPromptDriver -from griptape.memory.structure import ConversationMemory from griptape.memory import TaskMemory -from tests.mocks.mock_serializable import MockSerializable +from griptape.memory.structure import ConversationMemory from griptape.schemas import BaseSchema -from griptape.artifacts import BaseArtifact, TextArtifact +from tests.mocks.mock_serializable import MockSerializable class TestSerializableMixin: diff --git a/tests/unit/schemas/test_base_schema.py b/tests/unit/schemas/test_base_schema.py index fcbd08c7f..f3a3f0c1f 100644 --- a/tests/unit/schemas/test_base_schema.py +++ b/tests/unit/schemas/test_base_schema.py @@ -1,13 +1,16 @@ from __future__ import annotations + from datetime import datetime +from typing import Literal, Optional, Union + import pytest -from typing import Union, Optional, Literal from marshmallow import fields + from griptape.artifacts import BaseArtifact, TextArtifact +from griptape.loaders import TextLoader from griptape.schemas import PolymorphicSchema -from griptape.schemas.bytes_field import Bytes from griptape.schemas.base_schema import BaseSchema -from griptape.loaders import TextLoader +from griptape.schemas.bytes_field import Bytes from tests.mocks.mock_serializable import MockSerializable @@ -62,8 +65,8 @@ def test_get_field_type_info(self): assert BaseSchema._get_field_type_info(list) == (list, (), False) - assert BaseSchema._get_field_type_info(Literal["foo"]) == (str, (), False) # pyright: ignore - assert BaseSchema._get_field_type_info(Literal[5]) == (int, (), False) # pyright: ignore + assert BaseSchema._get_field_type_info(Literal["foo"]) == (str, (), False) # pyright: ignore[reportArgumentType] + assert BaseSchema._get_field_type_info(Literal[5]) == (int, (), False) # pyright: ignore[reportArgumentType] def test_is_list_sequence(self): assert BaseSchema.is_list_sequence(list) diff --git a/tests/unit/structures/test_agent.py b/tests/unit/structures/test_agent.py index baceac825..a09ad0f9a 100644 --- a/tests/unit/structures/test_agent.py +++ b/tests/unit/structures/test_agent.py @@ -1,15 +1,15 @@ import pytest -from griptape.memory.structure import ConversationMemory + +from griptape.engines import PromptSummaryEngine from griptape.memory import TaskMemory +from griptape.memory.structure import ConversationMemory from griptape.memory.task.storage import TextArtifactStorage from griptape.rules import Rule, Ruleset from griptape.structures import Agent -from griptape.tasks import PromptTask, BaseTask, ToolkitTask -from griptape.engines import PromptSummaryEngine - +from griptape.tasks import BaseTask, PromptTask, ToolkitTask +from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tool.tool import MockTool -from tests.mocks.mock_embedding_driver import MockEmbeddingDriver class TestAgent: @@ -49,8 +49,8 @@ def test_rules_and_rulesets(self): with pytest.raises(ValueError): Agent(rules=[Rule("foo test")], rulesets=[Ruleset("Bar", [Rule("bar test")])]) + agent = Agent() with pytest.raises(ValueError): - agent = Agent() agent.add_task(PromptTask(rules=[Rule("foo test")], rulesets=[Ruleset("Bar", [Rule("bar test")])])) def test_with_task_memory(self): @@ -149,13 +149,13 @@ def test_add_tasks(self): try: agent.add_tasks(first_task, second_task) - assert False + raise AssertionError() except ValueError: assert True try: agent + [first_task, second_task] - assert False + raise AssertionError() except ValueError: assert True diff --git a/tests/unit/structures/test_pipeline.py b/tests/unit/structures/test_pipeline.py index e63937a62..38f8abfb3 100644 --- a/tests/unit/structures/test_pipeline.py +++ b/tests/unit/structures/test_pipeline.py @@ -1,20 +1,21 @@ -import pytest import time -from griptape.artifacts import TextArtifact, ErrorArtifact +import pytest + +from griptape.artifacts import ErrorArtifact, TextArtifact +from griptape.memory.structure import ConversationMemory from griptape.memory.task.storage import TextArtifactStorage from griptape.rules import Rule, Ruleset +from griptape.structures import Pipeline +from griptape.tasks import BaseTask, CodeExecutionTask, PromptTask, ToolkitTask from griptape.tokenizers import OpenAiTokenizer -from griptape.tasks import PromptTask, BaseTask, ToolkitTask, CodeExecutionTask -from griptape.memory.structure import ConversationMemory from tests.mocks.mock_prompt_driver import MockPromptDriver -from griptape.structures import Pipeline from tests.mocks.mock_tool.tool import MockTool from tests.unit.structures.test_agent import MockEmbeddingDriver class TestPipeline: - @pytest.fixture + @pytest.fixture() def waiting_task(self): def fn(task): time.sleep(2) @@ -22,7 +23,7 @@ def fn(task): return CodeExecutionTask(run_fn=fn) - @pytest.fixture + @pytest.fixture() def error_artifact_task(self): def fn(task): return ErrorArtifact("error") @@ -76,8 +77,8 @@ def test_rules_and_rulesets(self): with pytest.raises(ValueError): Pipeline(rules=[Rule("foo test")], rulesets=[Ruleset("Bar", [Rule("bar test")])]) + pipeline = Pipeline() with pytest.raises(ValueError): - pipeline = Pipeline() pipeline.add_task(PromptTask(rules=[Rule("foo test")], rulesets=[Ruleset("Bar", [Rule("bar test")])])) def test_with_no_task_memory(self): diff --git a/tests/unit/structures/test_workflow.py b/tests/unit/structures/test_workflow.py index bf55e852f..2be164ea7 100644 --- a/tests/unit/structures/test_workflow.py +++ b/tests/unit/structures/test_workflow.py @@ -1,20 +1,20 @@ import time + import pytest -from pytest import fixture +from griptape.artifacts import ErrorArtifact, TextArtifact +from griptape.memory.structure import ConversationMemory from griptape.memory.task.storage import TextArtifactStorage -from tests.mocks.mock_prompt_driver import MockPromptDriver from griptape.rules import Rule, Ruleset -from griptape.tasks import PromptTask, BaseTask, ToolkitTask, CodeExecutionTask from griptape.structures import Workflow -from griptape.artifacts import ErrorArtifact, TextArtifact -from griptape.memory.structure import ConversationMemory -from tests.mocks.mock_tool.tool import MockTool +from griptape.tasks import BaseTask, CodeExecutionTask, PromptTask, ToolkitTask from tests.mocks.mock_embedding_driver import MockEmbeddingDriver +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.mocks.mock_tool.tool import MockTool class TestWorkflow: - @fixture + @pytest.fixture() def waiting_task(self): def fn(task): time.sleep(2) @@ -22,7 +22,7 @@ def fn(task): return CodeExecutionTask(run_fn=fn) - @fixture + @pytest.fixture() def error_artifact_task(self): def fn(task): return ErrorArtifact("error") @@ -75,8 +75,8 @@ def test_rules_and_rulesets(self): with pytest.raises(ValueError): Workflow(rules=[Rule("foo test")], rulesets=[Ruleset("Bar", [Rule("bar test")])]) + workflow = Workflow() with pytest.raises(ValueError): - workflow = Workflow() workflow.add_task(PromptTask(rules=[Rule("foo test")], rulesets=[Ruleset("Bar", [Rule("bar test")])])) def test_with_no_task_memory(self): @@ -777,7 +777,7 @@ def test_run_with_error_artifact_no_fail_fast(self, error_artifact_task, waiting assert workflow.output is not None @staticmethod - def _validate_topology_1(workflow): + def _validate_topology_1(workflow) -> None: assert len(workflow.tasks) == 4 assert workflow.input_task.id == "task1" assert workflow.output_task.id == "task4" @@ -805,8 +805,8 @@ def _validate_topology_1(workflow): assert task4.child_ids == [] @staticmethod - def _validate_topology_2(workflow): - """Adapted from https://en.wikipedia.org/wiki/Directed_acyclic_graph#/media/File:Tred-G.svg""" + def _validate_topology_2(workflow) -> None: + """Adapted from https://en.wikipedia.org/wiki/Directed_acyclic_graph#/media/File:Tred-G.svg.""" assert len(workflow.tasks) == 5 assert workflow.input_task.id == "taska" assert workflow.output_task.id == "taske" @@ -839,7 +839,7 @@ def _validate_topology_2(workflow): assert taske.child_ids == [] @staticmethod - def _validate_topology_3(workflow): + def _validate_topology_3(workflow) -> None: assert len(workflow.tasks) == 4 assert workflow.input_task.id == "task1" assert workflow.output_task.id == "task3" @@ -867,7 +867,7 @@ def _validate_topology_3(workflow): assert task4.child_ids == ["task2"] @staticmethod - def _validate_topology_4(workflow): + def _validate_topology_4(workflow) -> None: assert len(workflow.tasks) == 9 assert workflow.input_task.id == "collect_movie_info" assert workflow.output_task.id == "summarize_to_slack" diff --git a/tests/unit/tasks/test_actions_subtask.py b/tests/unit/tasks/test_actions_subtask.py index c6e5ca038..e25a42120 100644 --- a/tests/unit/tasks/test_actions_subtask.py +++ b/tests/unit/tasks/test_actions_subtask.py @@ -1,10 +1,11 @@ import json -from griptape.artifacts import ListArtifact, TextArtifact, ActionArtifact + +from griptape.artifacts import ActionArtifact, ListArtifact, TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact -from tests.mocks.mock_tool.tool import MockTool -from griptape.tasks import ToolkitTask, ActionsSubtask -from griptape.structures import Agent from griptape.common import ToolAction +from griptape.structures import Agent +from griptape.tasks import ActionsSubtask, ToolkitTask +from tests.mocks.mock_tool.tool import MockTool class TestActionsSubtask: diff --git a/tests/unit/tasks/test_audio_transcription_task.py b/tests/unit/tasks/test_audio_transcription_task.py index 3a53fd49d..f4bc0e8b8 100644 --- a/tests/unit/tasks/test_audio_transcription_task.py +++ b/tests/unit/tasks/test_audio_transcription_task.py @@ -5,17 +5,17 @@ from griptape.artifacts import AudioArtifact, TextArtifact from griptape.engines import AudioTranscriptionEngine from griptape.structures import Agent, Pipeline -from griptape.tasks import BaseTask, AudioTranscriptionTask +from griptape.tasks import AudioTranscriptionTask, BaseTask from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_structure_config import MockStructureConfig class TestAudioTranscriptionTask: - @pytest.fixture + @pytest.fixture() def audio_artifact(self): return AudioArtifact(value=b"audio data", format="mp3") - @pytest.fixture + @pytest.fixture() def audio_transcription_engine(self): return Mock() @@ -40,14 +40,9 @@ def test_config_audio_transcription_engine(self, audio_artifact): def test_run(self, audio_artifact, audio_transcription_engine): audio_transcription_engine.run.return_value = TextArtifact("mock transcription") - logger = Mock() task = AudioTranscriptionTask(audio_artifact, audio_transcription_engine=audio_transcription_engine) - pipeline = Pipeline(prompt_driver=MockPromptDriver(), logger=logger) + pipeline = Pipeline(prompt_driver=MockPromptDriver()) pipeline.add_task(task) assert pipeline.run().output.to_text() == "mock transcription" - - def test_before_run(self, audio_artifact, audio_transcription_engine): - task = AudioTranscriptionTask(audio_artifact, audio_transcription_engine=audio_transcription_engine) - task diff --git a/tests/unit/tasks/test_base_audio_input_task.py b/tests/unit/tasks/test_base_audio_input_task.py index e11074880..e16c6536c 100644 --- a/tests/unit/tasks/test_base_audio_input_task.py +++ b/tests/unit/tasks/test_base_audio_input_task.py @@ -1,12 +1,12 @@ import pytest -from tests.mocks.mock_audio_input_task import MockAudioInputTask from griptape.artifacts import AudioArtifact, TextArtifact +from tests.mocks.mock_audio_input_task import MockAudioInputTask from tests.mocks.mock_text_input_task import MockTextInputTask class TestBaseAudioInputTask: - @pytest.fixture + @pytest.fixture() def audio_artifact(self): return AudioArtifact(b"audio content", format="mp3") diff --git a/tests/unit/tasks/test_base_multi_text_input_task.py b/tests/unit/tasks/test_base_multi_text_input_task.py index ad4776aee..3d8d67a55 100644 --- a/tests/unit/tasks/test_base_multi_text_input_task.py +++ b/tests/unit/tasks/test_base_multi_text_input_task.py @@ -1,7 +1,7 @@ -from tests.mocks.mock_prompt_driver import MockPromptDriver -from griptape.structures import Pipeline from griptape.artifacts import TextArtifact +from griptape.structures import Pipeline from tests.mocks.mock_multi_text_input_task import MockMultiTextInputTask +from tests.mocks.mock_prompt_driver import MockPromptDriver class TestBaseMultiTextInputTask: diff --git a/tests/unit/tasks/test_base_task.py b/tests/unit/tasks/test_base_task.py index 7fe2810f5..7a1afcf07 100644 --- a/tests/unit/tasks/test_base_task.py +++ b/tests/unit/tasks/test_base_task.py @@ -1,9 +1,8 @@ import pytest from griptape.artifacts import TextArtifact -from griptape.structures import Agent +from griptape.structures import Agent, Workflow from griptape.tasks import ActionsSubtask -from griptape.structures import Workflow from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_task import MockTask @@ -11,7 +10,7 @@ class TestBaseTask: - @pytest.fixture + @pytest.fixture() def task(self): agent = Agent(prompt_driver=MockPromptDriver(), embedding_driver=MockEmbeddingDriver(), tools=[MockTool()]) diff --git a/tests/unit/tasks/test_base_text_input_task.py b/tests/unit/tasks/test_base_text_input_task.py index 14c3c3f2e..86dc98805 100644 --- a/tests/unit/tasks/test_base_text_input_task.py +++ b/tests/unit/tasks/test_base_text_input_task.py @@ -1,7 +1,7 @@ -from tests.mocks.mock_prompt_driver import MockPromptDriver -from griptape.structures import Pipeline from griptape.artifacts import TextArtifact -from griptape.rules import Ruleset, Rule +from griptape.rules import Rule, Ruleset +from griptape.structures import Pipeline +from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_text_input_task import MockTextInputTask diff --git a/tests/unit/tasks/test_code_execution_task.py b/tests/unit/tasks/test_code_execution_task.py index b94714912..3178e29db 100644 --- a/tests/unit/tasks/test_code_execution_task.py +++ b/tests/unit/tasks/test_code_execution_task.py @@ -1,4 +1,4 @@ -from griptape.artifacts import BaseArtifact, TextArtifact, ErrorArtifact +from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.structures import Pipeline from griptape.tasks import CodeExecutionTask from tests.mocks.mock_prompt_driver import MockPromptDriver diff --git a/tests/unit/tasks/test_csv_extraction_task.py b/tests/unit/tasks/test_csv_extraction_task.py index 9b8fb15bb..7d37c3897 100644 --- a/tests/unit/tasks/test_csv_extraction_task.py +++ b/tests/unit/tasks/test_csv_extraction_task.py @@ -8,7 +8,7 @@ class TestCsvExtractionTask: - @pytest.fixture + @pytest.fixture() def task(self): return CsvExtractionTask(args={"column_names": ["test1"]}) @@ -30,4 +30,4 @@ def test_config_extraction_engine(self, task): def test_missing_extraction_engine(self, task): with pytest.raises(ValueError): - task.extraction_engine + task.extraction_engine # noqa: B018 diff --git a/tests/unit/tasks/test_extraction_task.py b/tests/unit/tasks/test_extraction_task.py index 5e5ec09f6..afa73a506 100644 --- a/tests/unit/tasks/test_extraction_task.py +++ b/tests/unit/tasks/test_extraction_task.py @@ -1,4 +1,5 @@ import pytest + from griptape.engines import CsvExtractionEngine from griptape.structures import Agent from griptape.tasks import ExtractionTask @@ -6,7 +7,7 @@ class TestExtractionTask: - @pytest.fixture + @pytest.fixture() def task(self): return ExtractionTask( extraction_engine=CsvExtractionEngine(prompt_driver=MockPromptDriver()), args={"column_names": ["test1"]} diff --git a/tests/unit/tasks/test_image_query_task.py b/tests/unit/tasks/test_image_query_task.py index dd4940213..549009fc1 100644 --- a/tests/unit/tasks/test_image_query_task.py +++ b/tests/unit/tasks/test_image_query_task.py @@ -12,18 +12,18 @@ class TestImageQueryTask: - @pytest.fixture + @pytest.fixture() def image_query_engine(self) -> Mock: mock = Mock() mock.run.return_value = TextArtifact("image") return mock - @pytest.fixture + @pytest.fixture() def text_artifact(self): return TextArtifact(value="some text") - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact(value=b"some image data", format="png", width=512, height=512) @@ -70,7 +70,7 @@ def test_missing_image_generation_engine(self, text_artifact, image_artifact): task = ImageQueryTask((text_artifact, [image_artifact, image_artifact])) with pytest.raises(ValueError, match="Image Query Engine"): - task.image_query_engine + task.image_query_engine # noqa: B018 def test_run(self, image_query_engine, text_artifact, image_artifact): task = ImageQueryTask((text_artifact, [image_artifact, image_artifact]), image_query_engine=image_query_engine) diff --git a/tests/unit/tasks/test_inpainting_image_generation_task.py b/tests/unit/tasks/test_inpainting_image_generation_task.py index 9dc6aff54..ff287d79a 100644 --- a/tests/unit/tasks/test_inpainting_image_generation_task.py +++ b/tests/unit/tasks/test_inpainting_image_generation_task.py @@ -1,21 +1,22 @@ -from griptape.artifacts.list_artifact import ListArtifact -from griptape.engines import InpaintingImageGenerationEngine from unittest.mock import Mock import pytest -from griptape.tasks import BaseTask, InpaintingImageGenerationTask -from griptape.artifacts import TextArtifact, ImageArtifact + +from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.artifacts.list_artifact import ListArtifact +from griptape.engines import InpaintingImageGenerationEngine from griptape.structures import Agent +from griptape.tasks import BaseTask, InpaintingImageGenerationTask from tests.mocks.mock_image_generation_driver import MockImageGenerationDriver from tests.mocks.mock_structure_config import MockStructureConfig class TestInpaintingImageGenerationTask: - @pytest.fixture + @pytest.fixture() def text_artifact(self): return TextArtifact(value="some text") - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact(value=b"some image data", format="png", width=512, height=512) @@ -59,4 +60,4 @@ def test_missing_image_generation_engine(self, text_artifact, image_artifact): task = InpaintingImageGenerationTask((text_artifact, image_artifact, image_artifact)) with pytest.raises(ValueError): - task.image_generation_engine + task.image_generation_engine # noqa: B018 diff --git a/tests/unit/tasks/test_json_extraction_task.py b/tests/unit/tasks/test_json_extraction_task.py index 0366652b0..ba7d1ce30 100644 --- a/tests/unit/tasks/test_json_extraction_task.py +++ b/tests/unit/tasks/test_json_extraction_task.py @@ -1,14 +1,15 @@ -from griptape.engines import JsonExtractionEngine import pytest from schema import Schema + +from griptape.engines import JsonExtractionEngine from griptape.structures import Agent from griptape.tasks import JsonExtractionTask -from tests.mocks.mock_structure_config import MockStructureConfig from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.mocks.mock_structure_config import MockStructureConfig class TestJsonExtractionTask: - @pytest.fixture + @pytest.fixture() def task(self): return JsonExtractionTask("foo", args={"template_schema": Schema({"foo": "bar"}).json_schema("TemplateSchema")}) @@ -34,4 +35,4 @@ def test_config_extraction_engine(self, task): def test_missing_extraction_engine(self, task): with pytest.raises(ValueError): - task.extraction_engine + task.extraction_engine # noqa: B018 diff --git a/tests/unit/tasks/test_outpainting_image_generation_task.py b/tests/unit/tasks/test_outpainting_image_generation_task.py index 148ea133d..7de530330 100644 --- a/tests/unit/tasks/test_outpainting_image_generation_task.py +++ b/tests/unit/tasks/test_outpainting_image_generation_task.py @@ -1,10 +1,10 @@ -from griptape.artifacts.list_artifact import ListArtifact -from griptape.engines import OutpaintingImageGenerationEngine from unittest.mock import Mock import pytest from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.artifacts.list_artifact import ListArtifact +from griptape.engines import OutpaintingImageGenerationEngine from griptape.structures import Agent from griptape.tasks import BaseTask, OutpaintingImageGenerationTask from tests.mocks.mock_image_generation_driver import MockImageGenerationDriver @@ -12,11 +12,11 @@ class TestOutpaintingImageGenerationTask: - @pytest.fixture + @pytest.fixture() def text_artifact(self): return TextArtifact(value="some text") - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact(value=b"some image data", format="png", width=512, height=512) @@ -60,4 +60,4 @@ def test_missing_image_generation_engine(self, text_artifact, image_artifact): task = OutpaintingImageGenerationTask((text_artifact, image_artifact, image_artifact)) with pytest.raises(ValueError): - task.image_generation_engine + task.image_generation_engine # noqa: B018 diff --git a/tests/unit/tasks/test_prompt_image_generation_task.py b/tests/unit/tasks/test_prompt_image_generation_task.py index 4f6117c07..c3add5720 100644 --- a/tests/unit/tasks/test_prompt_image_generation_task.py +++ b/tests/unit/tasks/test_prompt_image_generation_task.py @@ -1,4 +1,3 @@ -from tests.mocks.mock_image_generation_driver import MockImageGenerationDriver from unittest.mock import Mock import pytest @@ -7,6 +6,7 @@ from griptape.engines import PromptImageGenerationEngine from griptape.structures import Agent from griptape.tasks import BaseTask, PromptImageGenerationTask +from tests.mocks.mock_image_generation_driver import MockImageGenerationDriver from tests.mocks.mock_structure_config import MockStructureConfig @@ -37,4 +37,4 @@ def test_missing_summary_engine(self): task = PromptImageGenerationTask("foo bar") with pytest.raises(ValueError): - task.image_generation_engine + task.image_generation_engine # noqa: B018 diff --git a/tests/unit/tasks/test_prompt_task.py b/tests/unit/tasks/test_prompt_task.py index c76f0284b..083ea6da5 100644 --- a/tests/unit/tasks/test_prompt_task.py +++ b/tests/unit/tasks/test_prompt_task.py @@ -1,14 +1,15 @@ import pytest + from griptape.artifacts.image_artifact import ImageArtifact from griptape.artifacts.list_artifact import ListArtifact from griptape.artifacts.text_artifact import TextArtifact from griptape.memory.structure import ConversationMemory from griptape.memory.structure.run import Run -from tests.mocks.mock_structure_config import MockStructureConfig -from griptape.tasks import PromptTask from griptape.rules import Rule -from tests.mocks.mock_prompt_driver import MockPromptDriver from griptape.structures import Pipeline +from griptape.tasks import PromptTask +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.mocks.mock_structure_config import MockStructureConfig class TestPromptTask: @@ -37,7 +38,7 @@ def test_missing_prompt_driver(self): task = PromptTask("test") with pytest.raises(ValueError): - task.prompt_driver + task.prompt_driver # noqa: B018 def test_input(self): # Str diff --git a/tests/unit/tasks/test_rag_task.py b/tests/unit/tasks/test_rag_task.py index c9b82f208..b205d385a 100644 --- a/tests/unit/tasks/test_rag_task.py +++ b/tests/unit/tasks/test_rag_task.py @@ -1,4 +1,5 @@ import pytest + from griptape.engines.rag import RagEngine from griptape.engines.rag.modules import PromptResponseRagModule from griptape.engines.rag.stages import ResponseRagStage @@ -8,7 +9,7 @@ class TestRagTask: - @pytest.fixture + @pytest.fixture() def task(self): return RagTask( input="test", diff --git a/tests/unit/tasks/test_structure_run_task.py b/tests/unit/tasks/test_structure_run_task.py index d89e98c91..1053ade9e 100644 --- a/tests/unit/tasks/test_structure_run_task.py +++ b/tests/unit/tasks/test_structure_run_task.py @@ -1,8 +1,7 @@ +from griptape.drivers import LocalStructureRunDriver +from griptape.structures import Agent, Pipeline from griptape.tasks import StructureRunTask -from griptape.structures import Agent from tests.mocks.mock_prompt_driver import MockPromptDriver -from griptape.drivers import LocalStructureRunDriver -from griptape.structures import Pipeline class TestStructureRunTask: diff --git a/tests/unit/tasks/test_text_summary_task.py b/tests/unit/tasks/test_text_summary_task.py index d7a474373..bb08f9d31 100644 --- a/tests/unit/tasks/test_text_summary_task.py +++ b/tests/unit/tasks/test_text_summary_task.py @@ -1,9 +1,10 @@ import pytest -from tests.mocks.mock_structure_config import MockStructureConfig + from griptape.engines import PromptSummaryEngine +from griptape.structures import Agent from griptape.tasks import TextSummaryTask from tests.mocks.mock_prompt_driver import MockPromptDriver -from griptape.structures import Agent +from tests.mocks.mock_structure_config import MockStructureConfig class TestTextSummaryTask: @@ -34,4 +35,4 @@ def test_missing_summary_engine(self): task = TextSummaryTask("test") with pytest.raises(ValueError): - task.summary_engine + task.summary_engine # noqa: B018 diff --git a/tests/unit/tasks/test_text_to_speech_task.py b/tests/unit/tasks/test_text_to_speech_task.py index 7a8e49364..86bc1d2ce 100644 --- a/tests/unit/tasks/test_text_to_speech_task.py +++ b/tests/unit/tasks/test_text_to_speech_task.py @@ -1,6 +1,6 @@ from unittest.mock import Mock -from griptape.artifacts import TextArtifact, AudioArtifact +from griptape.artifacts import AudioArtifact, TextArtifact from griptape.engines import TextToSpeechEngine from griptape.structures import Agent, Pipeline from griptape.tasks import BaseTask, TextToSpeechTask diff --git a/tests/unit/tasks/test_tool_task.py b/tests/unit/tasks/test_tool_task.py index 2af8b73c3..dfc679919 100644 --- a/tests/unit/tasks/test_tool_task.py +++ b/tests/unit/tasks/test_tool_task.py @@ -1,8 +1,10 @@ import json + import pytest + from griptape.artifacts import TextArtifact from griptape.structures import Agent -from griptape.tasks import ToolTask, ActionsSubtask +from griptape.tasks import ActionsSubtask, ToolTask from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_prompt_driver import MockPromptDriver from tests.mocks.mock_tool.tool import MockTool @@ -163,7 +165,7 @@ class TestToolTask: "$schema": "http://json-schema.org/draft-07/schema#", } - @pytest.fixture + @pytest.fixture() def agent(self): output_dict = {"tag": "foo", "name": "MockTool", "path": "test", "input": {"values": {"test": "foobar"}}} diff --git a/tests/unit/tasks/test_toolkit_task.py b/tests/unit/tasks/test_toolkit_task.py index 2217ba70c..cd5dd21f8 100644 --- a/tests/unit/tasks/test_toolkit_task.py +++ b/tests/unit/tasks/test_toolkit_task.py @@ -1,9 +1,9 @@ from griptape.artifacts import ErrorArtifact, TextArtifact -from griptape.structures import Agent -from griptape.tasks import ToolkitTask, ActionsSubtask, PromptTask from griptape.common import ToolAction -from tests.mocks.mock_tool.tool import MockTool +from griptape.structures import Agent +from griptape.tasks import ActionsSubtask, PromptTask, ToolkitTask from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.mocks.mock_tool.tool import MockTool from tests.utils import defaults @@ -166,7 +166,7 @@ def test_init(self): try: ToolkitTask("test", tools=[MockTool(), MockTool()]) - assert False + raise AssertionError() except ValueError: assert True @@ -231,7 +231,7 @@ def test_init_from_prompt_1(self): assert subtask.output is None def test_init_from_prompt_2(self): - valid_input = """Thought: need to test\nObservation: test + valid_input = """Thought: need to test\nObservation: test observation\nAnswer: test output""" task = ToolkitTask("test", tools=[MockTool(name="Tool1")]) diff --git a/tests/unit/tasks/test_variation_image_generation_task.py b/tests/unit/tasks/test_variation_image_generation_task.py index 6a9533da3..3f865931f 100644 --- a/tests/unit/tasks/test_variation_image_generation_task.py +++ b/tests/unit/tasks/test_variation_image_generation_task.py @@ -1,21 +1,22 @@ -from griptape.artifacts.list_artifact import ListArtifact -from tests.mocks.mock_image_generation_driver import MockImageGenerationDriver -from tests.mocks.mock_structure_config import MockStructureConfig from unittest.mock import Mock import pytest -from griptape.tasks import BaseTask, VariationImageGenerationTask -from griptape.artifacts import TextArtifact, ImageArtifact + +from griptape.artifacts import ImageArtifact, TextArtifact +from griptape.artifacts.list_artifact import ListArtifact from griptape.engines import VariationImageGenerationEngine from griptape.structures import Agent +from griptape.tasks import BaseTask, VariationImageGenerationTask +from tests.mocks.mock_image_generation_driver import MockImageGenerationDriver +from tests.mocks.mock_structure_config import MockStructureConfig class TestVariationImageGenerationTask: - @pytest.fixture + @pytest.fixture() def text_artifact(self): return TextArtifact(value="some text") - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact(value=b"some image data", format="png", width=512, height=512) @@ -56,4 +57,4 @@ def test_missing_summary_engine(self, text_artifact, image_artifact): task = VariationImageGenerationTask((text_artifact, image_artifact)) with pytest.raises(ValueError): - task.image_generation_engine + task.image_generation_engine # noqa: B018 diff --git a/tests/unit/tokenizers/test_amazon_bedrock_tokenizer.py b/tests/unit/tokenizers/test_amazon_bedrock_tokenizer.py index 2b77ba3dc..bb928c1c3 100644 --- a/tests/unit/tokenizers/test_amazon_bedrock_tokenizer.py +++ b/tests/unit/tokenizers/test_amazon_bedrock_tokenizer.py @@ -1,14 +1,15 @@ -from griptape.tokenizers import AmazonBedrockTokenizer import pytest +from griptape.tokenizers import AmazonBedrockTokenizer + class TestAmazonBedrockTokenizer: - @pytest.fixture + @pytest.fixture() def tokenizer(self, request): return AmazonBedrockTokenizer(model=request.param) @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("anthropic.claude-v2:1", 4), ("anthropic.claude-v2", 4), @@ -21,7 +22,7 @@ def test_token_count(self, tokenizer, expected): assert tokenizer.count_tokens("foo bar huzzah") == expected @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("anthropic.claude-v2", 99996), ("anthropic.claude-v2:1", 199996), @@ -34,7 +35,7 @@ def test_input_tokens_left(self, tokenizer, expected): assert tokenizer.count_input_tokens_left("foo bar huzzah") == expected @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("anthropic.claude-v2", 4092), ("anthropic.claude-v2:1", 4092), diff --git a/tests/unit/tokenizers/test_anthropic_tokenizer.py b/tests/unit/tokenizers/test_anthropic_tokenizer.py index ee165d270..859ba9684 100644 --- a/tests/unit/tokenizers/test_anthropic_tokenizer.py +++ b/tests/unit/tokenizers/test_anthropic_tokenizer.py @@ -1,14 +1,15 @@ import pytest + from griptape.tokenizers import AnthropicTokenizer class TestAnthropicTokenizer: - @pytest.fixture + @pytest.fixture() def tokenizer(self, request): return AnthropicTokenizer(model=request.param) @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [("claude-2.1", 5), ("claude-2.0", 5), ("claude-3-opus", 5), ("claude-3-sonnet", 5), ("claude-3-haiku", 5)], indirect=["tokenizer"], ) @@ -16,7 +17,7 @@ def test_token_count(self, tokenizer, expected): assert tokenizer.count_tokens("foo bar huzzah") == expected @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("claude-2.0", 99995), ("claude-2.1", 199995), @@ -30,7 +31,7 @@ def test_input_tokens_left(self, tokenizer, expected): assert tokenizer.count_input_tokens_left("foo bar huzzah") == expected @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("claude-2.0", 4091), ("claude-2.1", 4091), diff --git a/tests/unit/tokenizers/test_base_tokenizer.py b/tests/unit/tokenizers/test_base_tokenizer.py index eed15b9b2..08fd42c72 100644 --- a/tests/unit/tokenizers/test_base_tokenizer.py +++ b/tests/unit/tokenizers/test_base_tokenizer.py @@ -1,4 +1,5 @@ import logging + from tests.mocks.mock_tokenizer import MockTokenizer diff --git a/tests/unit/tokenizers/test_cohere_tokenizer.py b/tests/unit/tokenizers/test_cohere_tokenizer.py index 9ca23f4f0..3999ec399 100644 --- a/tests/unit/tokenizers/test_cohere_tokenizer.py +++ b/tests/unit/tokenizers/test_cohere_tokenizer.py @@ -1,5 +1,6 @@ import cohere import pytest + from griptape.tokenizers import CohereTokenizer @@ -10,7 +11,7 @@ def mock_client(self, mocker): return mock_client - @pytest.fixture + @pytest.fixture() def tokenizer(self): return CohereTokenizer(model="command", client=cohere.Client("foobar")) diff --git a/tests/unit/tokenizers/test_dummy_tokenizer.py b/tests/unit/tokenizers/test_dummy_tokenizer.py index 855fb6eee..5d770d1aa 100644 --- a/tests/unit/tokenizers/test_dummy_tokenizer.py +++ b/tests/unit/tokenizers/test_dummy_tokenizer.py @@ -1,10 +1,11 @@ import pytest + from griptape.exceptions import DummyException from griptape.tokenizers import DummyTokenizer class TestDummyTokenizer: - @pytest.fixture + @pytest.fixture() def tokenizer(self): return DummyTokenizer() diff --git a/tests/unit/tokenizers/test_google_tokenizer.py b/tests/unit/tokenizers/test_google_tokenizer.py index 34510cdac..41012f5d6 100644 --- a/tests/unit/tokenizers/test_google_tokenizer.py +++ b/tests/unit/tokenizers/test_google_tokenizer.py @@ -1,5 +1,7 @@ -import pytest from unittest.mock import Mock + +import pytest + from griptape.common import PromptStack from griptape.common.prompt_stack.messages.message import Message from griptape.tokenizers import GoogleTokenizer @@ -13,22 +15,22 @@ def mock_generative_model(self, mocker): return mock_generative_model - @pytest.fixture + @pytest.fixture() def tokenizer(self, request): return GoogleTokenizer(model=request.param, api_key="1234") - @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 5)], indirect=["tokenizer"]) + @pytest.mark.parametrize(("tokenizer", "expected"), [("gemini-pro", 5)], indirect=["tokenizer"]) def test_token_count(self, tokenizer, expected): assert tokenizer.count_tokens("foo bar huzzah") == expected assert tokenizer.count_tokens(PromptStack(messages=[Message(content="foo", role="user")])) == expected assert tokenizer.count_tokens(["foo", "bar", "huzzah"]) == expected - @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 30715)], indirect=["tokenizer"]) + @pytest.mark.parametrize(("tokenizer", "expected"), [("gemini-pro", 30715)], indirect=["tokenizer"]) def test_input_tokens_left(self, tokenizer, expected): assert tokenizer.count_input_tokens_left("foo bar huzzah") == expected assert tokenizer.count_input_tokens_left(["foo", "bar", "huzzah"]) == expected - @pytest.mark.parametrize("tokenizer,expected", [("gemini-pro", 2043)], indirect=["tokenizer"]) + @pytest.mark.parametrize(("tokenizer", "expected"), [("gemini-pro", 2043)], indirect=["tokenizer"]) def test_output_tokens_left(self, tokenizer, expected): assert tokenizer.count_output_tokens_left("foo bar huzzah") == expected assert tokenizer.count_output_tokens_left(["foo", "bar", "huzzah"]) == expected diff --git a/tests/unit/tokenizers/test_hugging_face_tokenizer.py b/tests/unit/tokenizers/test_hugging_face_tokenizer.py index dcb309a84..e717140e3 100644 --- a/tests/unit/tokenizers/test_hugging_face_tokenizer.py +++ b/tests/unit/tokenizers/test_hugging_face_tokenizer.py @@ -3,11 +3,12 @@ environ["TRANSFORMERS_VERBOSITY"] = "error" import pytest # noqa: E402 + from griptape.tokenizers import HuggingFaceTokenizer # noqa: E402 class TestHuggingFaceTokenizer: - @pytest.fixture + @pytest.fixture() def tokenizer(self): return HuggingFaceTokenizer(model="gpt2", max_output_tokens=1024) diff --git a/tests/unit/tokenizers/test_openai_tokenizer.py b/tests/unit/tokenizers/test_openai_tokenizer.py index 4aa42a87a..697184546 100644 --- a/tests/unit/tokenizers/test_openai_tokenizer.py +++ b/tests/unit/tokenizers/test_openai_tokenizer.py @@ -1,14 +1,15 @@ import pytest + from griptape.tokenizers import OpenAiTokenizer class TestOpenAiTokenizer: - @pytest.fixture + @pytest.fixture() def tokenizer(self, request): return OpenAiTokenizer(model=request.param) @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("gpt-4-1106", 5), ("gpt-4-32k", 5), @@ -34,7 +35,7 @@ def test_initialize_with_unknown_model(self): assert tokenizer.max_input_tokens == OpenAiTokenizer.DEFAULT_MAX_TOKENS - OpenAiTokenizer.TOKEN_OFFSET @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("gpt-4-1106", 19), ("gpt-4-32k", 19), @@ -45,7 +46,6 @@ def test_initialize_with_unknown_model(self): ("gpt-3.5-turbo", 19), ("gpt-35-turbo-16k", 19), ("gpt-35-turbo", 19), - ("gpt-35-turbo", 19), ], indirect=["tokenizer"], ) @@ -57,7 +57,7 @@ def test_token_count_for_messages(self, tokenizer, expected): == expected ) - @pytest.mark.parametrize("tokenizer,expected", [("not-real-model", 19)], indirect=["tokenizer"]) + @pytest.mark.parametrize(("tokenizer", "expected"), [("not-real-model", 19)], indirect=["tokenizer"]) def test_token_count_for_messages_unknown_model(self, tokenizer, expected): with pytest.raises(NotImplementedError): tokenizer.count_tokens( @@ -65,7 +65,7 @@ def test_token_count_for_messages_unknown_model(self, tokenizer, expected): ) @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("gpt-4-1106", 127987), ("gpt-4o", 127987), @@ -86,7 +86,7 @@ def test_input_tokens_left(self, tokenizer, expected): assert tokenizer.count_input_tokens_left("foo bar huzzah") == expected @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [ ("gpt-4-1106", 4091), ("gpt-4-32k", 4091), diff --git a/tests/unit/tokenizers/test_simple_tokenizer.py b/tests/unit/tokenizers/test_simple_tokenizer.py index a34c0d481..d2598067a 100644 --- a/tests/unit/tokenizers/test_simple_tokenizer.py +++ b/tests/unit/tokenizers/test_simple_tokenizer.py @@ -1,9 +1,10 @@ import pytest + from griptape.tokenizers import SimpleTokenizer class TestSimpleTokenizer: - @pytest.fixture + @pytest.fixture() def tokenizer(self): return SimpleTokenizer(max_input_tokens=1024, max_output_tokens=4096, characters_per_token=6) diff --git a/tests/unit/tokenizers/test_voyageai_tokenizer.py b/tests/unit/tokenizers/test_voyageai_tokenizer.py index 46c9490f7..6f631ae4e 100644 --- a/tests/unit/tokenizers/test_voyageai_tokenizer.py +++ b/tests/unit/tokenizers/test_voyageai_tokenizer.py @@ -1,4 +1,5 @@ import pytest + from griptape.tokenizers import VoyageAiTokenizer @@ -10,12 +11,12 @@ def mock_client(self, mocker): return mock_client - @pytest.fixture + @pytest.fixture() def tokenizer(self, request): return VoyageAiTokenizer(model=request.param) @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [("voyage-large-2", 5), ("voyage-code-2", 5), ("voyage-2", 5), ("voyage-lite-02-instruct", 5)], indirect=["tokenizer"], ) @@ -23,7 +24,7 @@ def test_token_count(self, tokenizer, expected): assert tokenizer.count_tokens("foo bar huzzah") == expected @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [("voyage-large-2", 15995), ("voyage-code-2", 15995), ("voyage-2", 3995), ("voyage-lite-02-instruct", 3995)], indirect=["tokenizer"], ) @@ -31,7 +32,7 @@ def test_input_tokens_left(self, tokenizer, expected): assert tokenizer.count_input_tokens_left("foo bar huzzah") == expected @pytest.mark.parametrize( - "tokenizer,expected", + ("tokenizer", "expected"), [("voyage-large-2", 0), ("voyage-code-2", 0), ("voyage-2", 0), ("voyage-lite-02-instruct", 0)], indirect=["tokenizer"], ) diff --git a/tests/unit/tools/test_aws_iam.py b/tests/unit/tools/test_aws_iam.py index 2a256425e..54dbaa5fb 100644 --- a/tests/unit/tools/test_aws_iam.py +++ b/tests/unit/tools/test_aws_iam.py @@ -1,12 +1,13 @@ -from pytest import fixture +import boto3 +import pytest + from griptape.tools import AwsIamClient from tests.utils.aws import mock_aws_credentials -import boto3 class TestAwsIamClient: - @fixture(autouse=True) - def run_before_and_after_tests(self): + @pytest.fixture(autouse=True) + def _run_before_and_after_tests(self): mock_aws_credentials() def test_get_user_policy(self): diff --git a/tests/unit/tools/test_aws_s3.py b/tests/unit/tools/test_aws_s3.py index 6fe62b71c..5c6a4c151 100644 --- a/tests/unit/tools/test_aws_s3.py +++ b/tests/unit/tools/test_aws_s3.py @@ -1,12 +1,13 @@ -from pytest import fixture +import boto3 +import pytest + from griptape.tools import AwsS3Client from tests.utils.aws import mock_aws_credentials -import boto3 class TestAwsS3Client: - @fixture(autouse=True) - def run_before_and_after_tests(self): + @pytest.fixture(autouse=True) + def _run_before_and_after_tests(self): mock_aws_credentials() def test_get_bucket_acl(self): diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index 75154b509..a4d4097c1 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -1,10 +1,12 @@ import inspect import os + import pytest import yaml -from schema import SchemaMissingKeyError, Schema, Or -from griptape.tasks import ActionsSubtask, ToolkitTask +from schema import Or, Schema, SchemaMissingKeyError + from griptape.common import ToolAction +from griptape.tasks import ActionsSubtask, ToolkitTask from tests.mocks.mock_tool.tool import MockTool from tests.utils import defaults @@ -153,7 +155,7 @@ class TestBaseTool: "$schema": "http://json-schema.org/draft-07/schema#", } - @pytest.fixture + @pytest.fixture() def tool(self): return MockTool(test_field="hello", test_int=5, test_dict={"foo": "bar"}) @@ -195,9 +197,9 @@ def test_validate(self, tool): def test_invalid_config(self): try: - from tests.mocks.invalid_mock_tool.tool import InvalidMockTool # noqa + from tests.mocks.invalid_mock_tool.tool import InvalidMockTool # noqa: F401 - assert False + raise AssertionError() except SchemaMissingKeyError: assert True @@ -252,6 +254,6 @@ def test_to_native_tool_name(self, tool): assert tool.to_native_tool_name(tool.test) == "MockTool_test" + tool.name = "mock_tool" with pytest.raises(ValueError): - tool.name = "mock_tool" tool.to_native_tool_name(tool.foo) diff --git a/tests/unit/tools/test_computer.py b/tests/unit/tools/test_computer.py index b11fd080e..95de18ae3 100644 --- a/tests/unit/tools/test_computer.py +++ b/tests/unit/tools/test_computer.py @@ -1,10 +1,11 @@ import pytest -from tests.mocks.docker.fake_api_client import make_fake_client + from griptape.tools import Computer +from tests.mocks.docker.fake_api_client import make_fake_client class TestComputer: - @pytest.fixture + @pytest.fixture() def computer(self): return Computer(docker_client=make_fake_client(), install_dependencies_on_init=False) diff --git a/tests/unit/tools/test_date_time.py b/tests/unit/tools/test_date_time.py index daa511f04..c534ae69b 100644 --- a/tests/unit/tools/test_date_time.py +++ b/tests/unit/tools/test_date_time.py @@ -1,6 +1,7 @@ -from griptape.tools import DateTime from datetime import datetime +from griptape.tools import DateTime + class TestDateTime: def test_get_current_datetime(self): diff --git a/tests/unit/tools/test_email_client.py b/tests/unit/tools/test_email_client.py index 183d7b265..cf99009b8 100644 --- a/tests/unit/tools/test_email_client.py +++ b/tests/unit/tools/test_email_client.py @@ -1,8 +1,8 @@ -from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact +import pytest + +from griptape.artifacts import ErrorArtifact, InfoArtifact, ListArtifact, TextArtifact from griptape.loaders.email_loader import EmailLoader -from griptape.artifacts import TextArtifact from griptape.tools import EmailClient -import pytest class TestEmailClient: @@ -27,7 +27,7 @@ def mock_smtp_ssl(self, mocker): mock_smtp_ssl.__enter__.return_value = mock_smtp_ssl return mock_smtp_ssl - @pytest.fixture + @pytest.fixture() def client(self): return EmailClient( username="fake-username", @@ -37,12 +37,12 @@ def client(self): mailboxes={"INBOX": "default mailbox for incoming email", "SENT": "default mailbox for sent email"}, ) - @pytest.fixture + @pytest.fixture() def send_params(self): return {"values": {"to": "fake@fake.fake", "subject": "fake-subject", "body": "fake-body"}} @pytest.mark.parametrize( - "values,query", + ("values", "query"), [ ({"label": "fake-label"}, EmailLoader.EmailQuery(label="fake-label")), ({"label": "fake-label", "key": "fake-key"}, EmailLoader.EmailQuery(label="fake-label", key="fake-key")), diff --git a/tests/unit/tools/test_file_manager.py b/tests/unit/tools/test_file_manager.py index 06c49f32b..57dd2c83e 100644 --- a/tests/unit/tools/test_file_manager.py +++ b/tests/unit/tools/test_file_manager.py @@ -1,9 +1,11 @@ -import os.path import os +import os.path import tempfile from pathlib import Path + import pytest -from griptape.artifacts import TextArtifact, ListArtifact + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.artifacts.error_artifact import ErrorArtifact from griptape.drivers.file_manager.local_file_manager_driver import LocalFileManagerDriver from griptape.loaders.text_loader import TextLoader @@ -12,14 +14,14 @@ class TestFileManager: - @pytest.fixture + @pytest.fixture() def file_manager(self): return FileManager( input_memory=[defaults.text_task_memory("Memory1")], file_manager_driver=LocalFileManagerDriver(workdir=os.path.abspath(os.path.dirname(__file__))), ) - @pytest.fixture + @pytest.fixture() def temp_dir(self): with tempfile.TemporaryDirectory() as temp_dir: yield temp_dir diff --git a/tests/unit/tools/test_google_docs_client.py b/tests/unit/tools/test_google_docs_client.py index ad74fcaca..a42fddda3 100644 --- a/tests/unit/tools/test_google_docs_client.py +++ b/tests/unit/tools/test_google_docs_client.py @@ -2,7 +2,7 @@ class TestGoogleDocsClient: - @pytest.fixture + @pytest.fixture() def mock_docs_client(self): from griptape.tools import GoogleDocsClient diff --git a/tests/unit/tools/test_google_drive_client.py b/tests/unit/tools/test_google_drive_client.py index 5d2f62df7..55f3c168f 100644 --- a/tests/unit/tools/test_google_drive_client.py +++ b/tests/unit/tools/test_google_drive_client.py @@ -1,5 +1,5 @@ -from griptape.tools import GoogleDriveClient from griptape.artifacts import ErrorArtifact +from griptape.tools import GoogleDriveClient class TestGoogleDriveClient: diff --git a/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py b/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py index 9feba9cbf..7d75d8670 100644 --- a/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py +++ b/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py @@ -1,10 +1,11 @@ import pytest from requests import exceptions -from griptape.artifacts import TextArtifact, ErrorArtifact + +from griptape.artifacts import ErrorArtifact, TextArtifact class TestGriptapeCloudKnowledgeBaseClient: - @pytest.fixture + @pytest.fixture() def client(self, mocker): from griptape.tools import GriptapeCloudKnowledgeBaseClient @@ -22,7 +23,7 @@ def client(self, mocker): base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" ) - @pytest.fixture + @pytest.fixture() def client_no_description(self, mocker): from griptape.tools import GriptapeCloudKnowledgeBaseClient @@ -35,7 +36,7 @@ def client_no_description(self, mocker): base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" ) - @pytest.fixture + @pytest.fixture() def client_kb_not_found(self, mocker): from griptape.tools import GriptapeCloudKnowledgeBaseClient @@ -48,7 +49,7 @@ def client_kb_not_found(self, mocker): base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" ) - @pytest.fixture + @pytest.fixture() def client_kb_error(self, mocker): from griptape.tools import GriptapeCloudKnowledgeBaseClient @@ -75,10 +76,10 @@ def test_get_knowledge_base_description(self, client): def test_get_knowledge_base_description_error(self, client_no_description): exception_match_text = f"No description found for Knowledge Base {client_no_description.knowledge_base_id}. Please set a description, or manually set the `GriptapeCloudKnowledgeBaseClient.description` attribute." - with pytest.raises(ValueError, match=exception_match_text) as e: + with pytest.raises(ValueError, match=exception_match_text): client_no_description._get_knowledge_base_description() def test_get_knowledge_base_kb_error(self, client_kb_not_found): exception_match_text = f"Error accessing Knowledge Base {client_kb_not_found.knowledge_base_id}." - with pytest.raises(ValueError, match=exception_match_text) as e: + with pytest.raises(ValueError, match=exception_match_text): client_kb_not_found._get_knowledge_base_description() diff --git a/tests/unit/tools/test_inpainting_image_generation_client.py b/tests/unit/tools/test_inpainting_image_generation_client.py index 9e1d017bb..14ddcb5b6 100644 --- a/tests/unit/tools/test_inpainting_image_generation_client.py +++ b/tests/unit/tools/test_inpainting_image_generation_client.py @@ -10,18 +10,18 @@ class TestInpaintingImageGenerationClient: - @pytest.fixture + @pytest.fixture() def image_generation_engine(self) -> Mock: return Mock() - @pytest.fixture + @pytest.fixture() def image_loader(self) -> Mock: loader = Mock() loader.load.return_value = ImageArtifact(value=b"image_data", format="png", width=512, height=512) return loader - @pytest.fixture + @pytest.fixture() def image_generator(self, image_generation_engine, image_loader) -> InpaintingImageGenerationClient: return InpaintingImageGenerationClient(engine=image_generation_engine, image_loader=image_loader) @@ -53,7 +53,7 @@ def test_image_inpainting_with_outfile(self, image_generation_engine, image_load engine=image_generation_engine, output_file=outfile, image_loader=image_loader ) - image_generator.engine.run.return_value = Mock( # pyright: ignore + image_generator.engine.run.return_value = Mock( # pyright: ignore[reportFunctionMemberAccess] value=b"image data", format="png", width=512, height=512, model="test model", prompt="test prompt" ) diff --git a/tests/unit/tools/test_openweather_client.py b/tests/unit/tools/test_openweather_client.py index 319a7ec2a..89b80e164 100644 --- a/tests/unit/tools/test_openweather_client.py +++ b/tests/unit/tools/test_openweather_client.py @@ -1,16 +1,18 @@ -import pytest from unittest.mock import patch + +import pytest + from griptape.artifacts import ErrorArtifact from griptape.tools import OpenWeatherClient -@pytest.fixture +@pytest.fixture() def client(): return OpenWeatherClient(api_key="YOUR_API_KEY") class MockResponse: - def __init__(self, json_data, status_code): + def __init__(self, json_data, status_code) -> None: self.json_data = json_data self.status_code = status_code diff --git a/tests/unit/tools/test_outpainting_image_variation_client.py b/tests/unit/tools/test_outpainting_image_variation_client.py index 1a84018a4..d604574cb 100644 --- a/tests/unit/tools/test_outpainting_image_variation_client.py +++ b/tests/unit/tools/test_outpainting_image_variation_client.py @@ -10,18 +10,18 @@ class TestOutpaintingImageGenerationClient: - @pytest.fixture + @pytest.fixture() def image_generation_engine(self) -> Mock: return Mock() - @pytest.fixture + @pytest.fixture() def image_loader(self) -> Mock: loader = Mock() loader.load.return_value = ImageArtifact(value=b"image_data", format="png", width=512, height=512) return loader - @pytest.fixture + @pytest.fixture() def image_generator(self, image_generation_engine, image_loader) -> OutpaintingImageGenerationClient: return OutpaintingImageGenerationClient(engine=image_generation_engine, image_loader=image_loader) @@ -53,7 +53,7 @@ def test_image_outpainting_with_outfile(self, image_generation_engine, image_loa engine=image_generation_engine, output_file=outfile, image_loader=image_loader ) - image_generator.engine.run.return_value = Mock( # pyright: ignore + image_generator.engine.run.return_value = Mock( # pyright: ignore[reportFunctionMemberAccess] value=b"image data", format="png", width=512, height=512, model="test model", prompt="test prompt" ) diff --git a/tests/unit/tools/test_prompt_image_generation_client.py b/tests/unit/tools/test_prompt_image_generation_client.py index dffbb4239..7393d1eff 100644 --- a/tests/unit/tools/test_prompt_image_generation_client.py +++ b/tests/unit/tools/test_prompt_image_generation_client.py @@ -9,11 +9,11 @@ class TestPromptImageGenerationClient: - @pytest.fixture + @pytest.fixture() def image_generation_engine(self) -> Mock: return Mock() - @pytest.fixture + @pytest.fixture() def image_generator(self, image_generation_engine) -> PromptImageGenerationClient: return PromptImageGenerationClient(engine=image_generation_engine) @@ -36,7 +36,7 @@ def test_generate_image_with_outfile(self, image_generation_engine) -> None: outfile = f"{tempfile.gettempdir()}/{str(uuid.uuid4())}.png" image_generator = PromptImageGenerationClient(engine=image_generation_engine, output_file=outfile) - image_generator.engine.run.return_value = Mock( # pyright: ignore + image_generator.engine.run.return_value = Mock( # pyright: ignore[reportFunctionMemberAccess] value=b"image data", format="png", width=512, height=512, model="test model", prompt="test prompt" ) diff --git a/tests/unit/tools/test_rest_api_client.py b/tests/unit/tools/test_rest_api_client.py index b937b9f23..58f21d1f1 100644 --- a/tests/unit/tools/test_rest_api_client.py +++ b/tests/unit/tools/test_rest_api_client.py @@ -1,9 +1,10 @@ import pytest + from griptape.artifacts import BaseArtifact class TestRestApi: - @pytest.fixture + @pytest.fixture() def client(self): from griptape.tools import RestApiClient diff --git a/tests/unit/tools/test_sql_client.py b/tests/unit/tools/test_sql_client.py index 6584fa752..8ab61fc8f 100644 --- a/tests/unit/tools/test_sql_client.py +++ b/tests/unit/tools/test_sql_client.py @@ -1,12 +1,14 @@ +import sqlite3 + import pytest + from griptape.drivers import SqlDriver from griptape.loaders import SqlLoader from griptape.tools import SqlClient -import sqlite3 class TestSqlClient: - @pytest.fixture + @pytest.fixture() def driver(self): new_driver = SqlDriver(engine_url="sqlite:///:memory:") diff --git a/tests/unit/tools/test_structure_run_client.py b/tests/unit/tools/test_structure_run_client.py index b57bfb28f..d498b7c56 100644 --- a/tests/unit/tools/test_structure_run_client.py +++ b/tests/unit/tools/test_structure_run_client.py @@ -1,12 +1,13 @@ import pytest + from griptape.drivers.structure_run.local_structure_run_driver import LocalStructureRunDriver -from griptape.tools import StructureRunClient from griptape.structures import Agent +from griptape.tools import StructureRunClient from tests.mocks.mock_prompt_driver import MockPromptDriver class TestStructureRunClient: - @pytest.fixture + @pytest.fixture() def client(self): driver = MockPromptDriver() agent = Agent(prompt_driver=driver) diff --git a/tests/unit/tools/test_task_memory_client.py b/tests/unit/tools/test_task_memory_client.py index 3956ae415..4276b89ec 100644 --- a/tests/unit/tools/test_task_memory_client.py +++ b/tests/unit/tools/test_task_memory_client.py @@ -1,11 +1,12 @@ import pytest + from griptape.artifacts import TextArtifact from griptape.tools import TaskMemoryClient from tests.utils import defaults class TestTaskMemoryClient: - @pytest.fixture + @pytest.fixture() def tool(self): return TaskMemoryClient(off_prompt=True, input_memory=[defaults.text_task_memory("TestMemory")]) diff --git a/tests/unit/tools/test_text_to_speech_client.py b/tests/unit/tools/test_text_to_speech_client.py index 881b1234d..0b9061aa6 100644 --- a/tests/unit/tools/test_text_to_speech_client.py +++ b/tests/unit/tools/test_text_to_speech_client.py @@ -9,11 +9,11 @@ class TestTextToSpeechClient: - @pytest.fixture + @pytest.fixture() def text_to_speech_engine(self) -> Mock: return Mock() - @pytest.fixture + @pytest.fixture() def text_to_speech_client(self, text_to_speech_engine) -> TextToSpeechClient: return TextToSpeechClient(engine=text_to_speech_engine) @@ -32,7 +32,7 @@ def test_text_to_speech_with_outfile(self, text_to_speech_engine) -> None: outfile = f"{tempfile.gettempdir()}/{str(uuid.uuid4())}.mp3" text_to_speech_client = TextToSpeechClient(engine=text_to_speech_engine, output_file=outfile) - text_to_speech_client.engine.run.return_value = Mock(value=b"audio data", format="mp3") # pyright: ignore + text_to_speech_client.engine.run.return_value = Mock(value=b"audio data", format="mp3") # pyright: ignore[reportFunctionMemberAccess] audio_artifact = text_to_speech_client.text_to_speech(params={"values": {"text": "say this!"}}) diff --git a/tests/unit/tools/test_transcription_client.py b/tests/unit/tools/test_transcription_client.py index ea6bd3453..7768792d0 100644 --- a/tests/unit/tools/test_transcription_client.py +++ b/tests/unit/tools/test_transcription_client.py @@ -7,11 +7,11 @@ class TestTranscriptionClient: - @pytest.fixture + @pytest.fixture() def transcription_engine(self) -> Mock: return Mock() - @pytest.fixture + @pytest.fixture() def audio_loader(self) -> Mock: loader = Mock() loader.load.return_value = AudioArtifact(value=b"audio data", format="wav") @@ -24,7 +24,7 @@ def test_init_transcription_client(self, transcription_engine, audio_loader) -> @patch("builtins.open", mock_open(read_data=b"audio data")) def test_transcribe_audio_from_disk(self, transcription_engine, audio_loader) -> None: client = AudioTranscriptionClient(engine=transcription_engine, audio_loader=audio_loader) - client.engine.run.return_value = Mock(value="transcription") # pyright: ignore + client.engine.run.return_value = Mock(value="transcription") # pyright: ignore[reportFunctionMemberAccess] text_artifact = client.transcribe_audio_from_disk(params={"values": {"path": "audio.wav"}}) @@ -37,7 +37,7 @@ def test_transcribe_audio_from_memory(self, transcription_engine, audio_loader) memory.load_artifacts = Mock(return_value=[AudioArtifact(value=b"audio data", format="wav", name="name")]) client.find_input_memory = Mock(return_value=memory) - client.engine.run.return_value = Mock(value="transcription") # pyright: ignore + client.engine.run.return_value = Mock(value="transcription") # pyright: ignore[reportFunctionMemberAccess] text_artifact = client.transcribe_audio_from_memory( params={"values": {"memory_name": "memory", "artifact_namespace": "namespace", "artifact_name": "name"}} diff --git a/tests/unit/tools/test_variation_image_generation_client.py b/tests/unit/tools/test_variation_image_generation_client.py index b29f4fecf..ba707e5bb 100644 --- a/tests/unit/tools/test_variation_image_generation_client.py +++ b/tests/unit/tools/test_variation_image_generation_client.py @@ -10,18 +10,18 @@ class TestVariationImageGenerationClient: - @pytest.fixture + @pytest.fixture() def image_generation_engine(self) -> Mock: return Mock() - @pytest.fixture + @pytest.fixture() def image_loader(self) -> Mock: loader = Mock() loader.load.return_value = ImageArtifact(value=b"image_data", format="png", width=512, height=512) return loader - @pytest.fixture + @pytest.fixture() def image_generator(self, image_generation_engine, image_loader) -> VariationImageGenerationClient: return VariationImageGenerationClient(engine=image_generation_engine, image_loader=image_loader) @@ -54,7 +54,7 @@ def test_image_variation_with_outfile(self, image_generation_engine, image_loade engine=image_generation_engine, output_file=outfile, image_loader=image_loader ) - image_generator.engine.run.return_value = Mock( # pyright: ignore + image_generator.engine.run.return_value = Mock( # pyright: ignore[reportFunctionMemberAccess] value=b"image data", format="png", width=512, height=512, model="test model", prompt="test prompt" ) diff --git a/tests/unit/tools/test_vector_store_client.py b/tests/unit/tools/test_vector_store_client.py index 45018b847..b02dda226 100644 --- a/tests/unit/tools/test_vector_store_client.py +++ b/tests/unit/tools/test_vector_store_client.py @@ -1,5 +1,6 @@ import pytest -from griptape.artifacts import TextArtifact, ListArtifact + +from griptape.artifacts import ListArtifact, TextArtifact from griptape.drivers import LocalVectorStoreDriver from griptape.tools import VectorStoreClient from tests.mocks.mock_embedding_driver import MockEmbeddingDriver @@ -7,7 +8,7 @@ class TestVectorStoreClient: @pytest.fixture(autouse=True) - def mock_try_run(self, mocker): + def _mock_try_run(self, mocker): mocker.patch("griptape.drivers.OpenAiEmbeddingDriver.try_embed_chunk", return_value=[0, 1]) def test_search(self): @@ -16,7 +17,7 @@ def test_search(self): driver.upsert_text_artifacts({"test": [TextArtifact("foo"), TextArtifact("bar")]}) - assert set([a.value for a in tool.search({"values": {"query": "test"}})]) == {"foo", "bar"} + assert {a.value for a in tool.search({"values": {"query": "test"}})} == {"foo", "bar"} def test_search_with_namespace(self): driver = LocalVectorStoreDriver(embedding_driver=MockEmbeddingDriver()) diff --git a/tests/unit/tools/test_web_scraper.py b/tests/unit/tools/test_web_scraper.py index f46004e8f..30362ce65 100644 --- a/tests/unit/tools/test_web_scraper.py +++ b/tests/unit/tools/test_web_scraper.py @@ -1,9 +1,10 @@ import pytest + from griptape.artifacts import ListArtifact class TestWebScraper: - @pytest.fixture + @pytest.fixture() def scraper(self): from griptape.tools import WebScraper diff --git a/tests/unit/tools/test_web_search.py b/tests/unit/tools/test_web_search.py index 0abc880c8..dd447de5d 100644 --- a/tests/unit/tools/test_web_search.py +++ b/tests/unit/tools/test_web_search.py @@ -1,10 +1,11 @@ import pytest + from griptape.artifacts import BaseArtifact, ErrorArtifact, TextArtifact from griptape.tools import WebSearch class TestWebSearch: - @pytest.fixture + @pytest.fixture() def websearch_tool(self, mocker): mock_response = TextArtifact("test_response") driver = mocker.Mock() @@ -12,7 +13,7 @@ def websearch_tool(self, mocker): return WebSearch(web_search_driver=driver) - @pytest.fixture + @pytest.fixture() def websearch_tool_with_error(self, mocker): mock_response = Exception("test_error") driver = mocker.Mock() diff --git a/tests/unit/utils/test_base_tokenizer.py b/tests/unit/utils/test_base_tokenizer.py index eed15b9b2..08fd42c72 100644 --- a/tests/unit/utils/test_base_tokenizer.py +++ b/tests/unit/utils/test_base_tokenizer.py @@ -1,4 +1,5 @@ import logging + from tests.mocks.mock_tokenizer import MockTokenizer diff --git a/tests/unit/utils/test_command_runner.py b/tests/unit/utils/test_command_runner.py index 4ca3afebc..25b7fd8c3 100644 --- a/tests/unit/utils/test_command_runner.py +++ b/tests/unit/utils/test_command_runner.py @@ -1,4 +1,3 @@ -from griptape.artifacts import TextArtifact from griptape.utils import CommandRunner diff --git a/tests/unit/utils/test_conversation.py b/tests/unit/utils/test_conversation.py index cce067f73..28ee72409 100644 --- a/tests/unit/utils/test_conversation.py +++ b/tests/unit/utils/test_conversation.py @@ -1,8 +1,8 @@ -from tests.mocks.mock_prompt_driver import MockPromptDriver from griptape.memory.structure import ConversationMemory, SummaryConversationMemory -from griptape.tasks import PromptTask from griptape.structures import Pipeline +from griptape.tasks import PromptTask from griptape.utils import Conversation +from tests.mocks.mock_prompt_driver import MockPromptDriver class TestConversation: diff --git a/tests/unit/utils/test_deprecate.py b/tests/unit/utils/test_deprecate.py index 0c8064f8d..868dbd60f 100644 --- a/tests/unit/utils/test_deprecate.py +++ b/tests/unit/utils/test_deprecate.py @@ -1,4 +1,5 @@ import pytest + from griptape.utils.deprecation import deprecation_warn diff --git a/tests/unit/utils/test_dict_utils.py b/tests/unit/utils/test_dict_utils.py index 4b4e4ca08..94e870e1a 100644 --- a/tests/unit/utils/test_dict_utils.py +++ b/tests/unit/utils/test_dict_utils.py @@ -1,6 +1,7 @@ -from griptape.utils import remove_null_values_in_dict_recursively, dict_merge, remove_key_in_dict_recursively import pytest +from griptape.utils import dict_merge, remove_key_in_dict_recursively, remove_null_values_in_dict_recursively + class TestDictUtils: def test_remove_null_values_in_dict_recursively(self): diff --git a/tests/unit/utils/test_file_utils.py b/tests/unit/utils/test_file_utils.py index dbcf1044b..de1882ef5 100644 --- a/tests/unit/utils/test_file_utils.py +++ b/tests/unit/utils/test_file_utils.py @@ -1,7 +1,8 @@ import os -from griptape.loaders import TextLoader -from griptape import utils from concurrent import futures + +from griptape import utils +from griptape.loaders import TextLoader from tests.mocks.mock_embedding_driver import MockEmbeddingDriver MAX_TOKENS = 50 diff --git a/tests/unit/utils/test_futures.py b/tests/unit/utils/test_futures.py index 5e30148a9..04ddb9877 100644 --- a/tests/unit/utils/test_futures.py +++ b/tests/unit/utils/test_futures.py @@ -1,4 +1,5 @@ from concurrent import futures + from griptape import utils diff --git a/tests/unit/utils/test_import_utils.py b/tests/unit/utils/test_import_utils.py index bcfb06c87..f6b2429d9 100644 --- a/tests/unit/utils/test_import_utils.py +++ b/tests/unit/utils/test_import_utils.py @@ -1,4 +1,5 @@ import pytest + from griptape.utils import import_optional_dependency, is_dependency_installed diff --git a/tests/unit/utils/test_load_artifact_from_memory.py b/tests/unit/utils/test_load_artifact_from_memory.py index db4f7d573..946ddd6e7 100644 --- a/tests/unit/utils/test_load_artifact_from_memory.py +++ b/tests/unit/utils/test_load_artifact_from_memory.py @@ -2,43 +2,39 @@ import pytest -from griptape.artifacts import TextArtifact, ErrorArtifact, ImageArtifact +from griptape.artifacts import ImageArtifact, TextArtifact from griptape.utils import load_artifact_from_memory class TestLoadImageArtifactFromMemory: - @pytest.fixture + @pytest.fixture() def memory(self): return Mock() - @pytest.fixture + @pytest.fixture() def text_artifact(self): return TextArtifact(value="text", name="text") - @pytest.fixture + @pytest.fixture() def image_artifact(self): return ImageArtifact(value=b"image", name="image", format="png", height=32, width=32) def test_no_memory(self): with pytest.raises(ValueError): - load_artifact_from_memory(None, "", "", TextArtifact) # pyright: ignore + load_artifact_from_memory(None, "", "", TextArtifact) # pyright: ignore[reportArgumentType] def test_no_artifacts_in_memory(self, memory): memory.load_artifacts.return_value = [] - with pytest.raises(ValueError) as e: + with pytest.raises(ValueError, match="no artifacts found in namespace"): load_artifact_from_memory(memory, "", "", TextArtifact) - assert str(e) == "no artifacts found in namespace" - def test_no_artifacts_by_name(self, memory, text_artifact): memory.load_artifacts.return_value = [text_artifact] - with pytest.raises(ValueError) as e: + with pytest.raises(ValueError, match="artifact other_name not found in namespace namespace"): load_artifact_from_memory(memory, "namespace", "other_name", TextArtifact) - assert str(e) == "artifact name not found in namespace" - def test_returns_one_artifact(self, memory, text_artifact): memory.load_artifacts.return_value = [text_artifact] @@ -56,7 +52,5 @@ def test_returns_multiple_artifacts(self, memory, text_artifact, image_artifact) def test_wrong_artifact_type(self, memory, image_artifact): memory.load_artifacts.return_value = [image_artifact] - with pytest.raises(ValueError) as e: + with pytest.raises(ValueError, match="image is not of type"): load_artifact_from_memory(memory, "namespace", image_artifact.name, TextArtifact) - - assert str(e) == "artifact is not of type ImageArtifact" diff --git a/tests/unit/utils/test_message_stack.py b/tests/unit/utils/test_message_stack.py index 908388a33..799705a54 100644 --- a/tests/unit/utils/test_message_stack.py +++ b/tests/unit/utils/test_message_stack.py @@ -5,7 +5,7 @@ class TestPromptStack: - @pytest.fixture + @pytest.fixture() def prompt_stack(self): return PromptStack() diff --git a/tests/unit/utils/test_stream.py b/tests/unit/utils/test_stream.py index 33c97cc75..767d31ba0 100644 --- a/tests/unit/utils/test_stream.py +++ b/tests/unit/utils/test_stream.py @@ -1,5 +1,7 @@ -from typing import Iterator +from collections.abc import Iterator + import pytest + from griptape.structures import Agent from griptape.utils import Stream from tests.mocks.mock_prompt_driver import MockPromptDriver @@ -20,9 +22,9 @@ def test_init(self, agent): chat_stream_artifact = next(chat_stream_run) assert chat_stream_artifact.value == "mock output" + next(chat_stream_run) with pytest.raises(StopIteration): next(chat_stream_run) - next(chat_stream_run) else: with pytest.raises(ValueError): Stream(agent) diff --git a/tests/unit/utils/test_structure_visualizer.py b/tests/unit/utils/test_structure_visualizer.py index e16275a5c..f6e621b91 100644 --- a/tests/unit/utils/test_structure_visualizer.py +++ b/tests/unit/utils/test_structure_visualizer.py @@ -1,7 +1,7 @@ -from tests.mocks.mock_prompt_driver import MockPromptDriver -from griptape.utils import StructureVisualizer +from griptape.structures import Agent, Pipeline, Workflow from griptape.tasks import PromptTask -from griptape.structures import Agent, Workflow, Pipeline +from griptape.utils import StructureVisualizer +from tests.mocks.mock_prompt_driver import MockPromptDriver class TestStructureVisualizer: diff --git a/tests/utils/code_blocks.py b/tests/utils/code_blocks.py index 9cfebb987..ca5b193d1 100644 --- a/tests/utils/code_blocks.py +++ b/tests/utils/code_blocks.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import logging import pathlib import textwrap @@ -6,7 +8,7 @@ def check_py_string(source: str) -> None: - """Exec the python source given in a new module namespace + """Exec the python source given in a new module namespace. Does not return anything, but exceptions raised by the source will propagate out unmodified diff --git a/tests/utils/defaults.py b/tests/utils/defaults.py index 5a9f6f958..bad7f0d79 100644 --- a/tests/utils/defaults.py +++ b/tests/utils/defaults.py @@ -1,11 +1,11 @@ -from griptape.artifacts import TextArtifact, BlobArtifact +from griptape.artifacts import BlobArtifact, TextArtifact from griptape.drivers import LocalVectorStoreDriver -from griptape.engines import PromptSummaryEngine, CsvExtractionEngine, JsonExtractionEngine +from griptape.engines import CsvExtractionEngine, JsonExtractionEngine, PromptSummaryEngine from griptape.engines.rag import RagEngine -from griptape.engines.rag.modules import VectorStoreRetrievalRagModule, PromptResponseRagModule -from griptape.engines.rag.stages import RetrievalRagStage, ResponseRagStage +from griptape.engines.rag.modules import PromptResponseRagModule, VectorStoreRetrievalRagModule +from griptape.engines.rag.stages import ResponseRagStage, RetrievalRagStage from griptape.memory import TaskMemory -from griptape.memory.task.storage import TextArtifactStorage, BlobArtifactStorage +from griptape.memory.task.storage import BlobArtifactStorage, TextArtifactStorage from tests.mocks.mock_embedding_driver import MockEmbeddingDriver from tests.mocks.mock_prompt_driver import MockPromptDriver diff --git a/tests/utils/postgres.py b/tests/utils/postgres.py index 1e04153bd..a320d9a05 100644 --- a/tests/utils/postgres.py +++ b/tests/utils/postgres.py @@ -1,4 +1,4 @@ -from psycopg2 import connect, OperationalError +from psycopg2 import OperationalError, connect def can_connect_to_postgres(user="postgres", password="postgres", host="localhost", port="5432", database="postgres"): diff --git a/tests/utils/structure_tester.py b/tests/utils/structure_tester.py index 8d62bc835..5b908065b 100644 --- a/tests/utils/structure_tester.py +++ b/tests/utils/structure_tester.py @@ -1,25 +1,26 @@ from __future__ import annotations -import os -from attrs import field, define -from schema import Schema, Literal -import logging + import json -from griptape.artifacts.error_artifact import ErrorArtifact +import logging +import os -from griptape.structures import Agent -from griptape.rules import Rule, Ruleset -from griptape.tasks import PromptTask -from griptape.structures import Structure +from attrs import define, field +from schema import Literal, Schema + +from griptape.artifacts.error_artifact import ErrorArtifact from griptape.drivers import ( - BasePromptDriver, AmazonBedrockPromptDriver, + AmazonSageMakerJumpstartPromptDriver, AnthropicPromptDriver, - CoherePromptDriver, - OpenAiChatPromptDriver, AzureOpenAiChatPromptDriver, - AmazonSageMakerJumpstartPromptDriver, + BasePromptDriver, + CoherePromptDriver, GooglePromptDriver, + OpenAiChatPromptDriver, ) +from griptape.rules import Rule, Ruleset +from griptape.structures import Agent, Structure +from griptape.tasks import PromptTask def get_enabled_prompt_drivers(prompt_drivers_options) -> list[BasePromptDriver]: @@ -295,7 +296,7 @@ def verify_structure_output(self, structure) -> dict: return result - def run(self, prompt, assert_correctness: bool = True) -> dict: + def run(self, prompt, *, assert_correctness: bool = True) -> dict: result = self.structure.run(prompt) if isinstance(result.output_task.output, ErrorArtifact): verified_result = {"correct": False, "explanation": f"ErrorArtifact: {result.output_task.output.to_text()}"} From f51447581d122ad58506e8928f45d1fbd59e1dad Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 16 Jul 2024 12:05:40 -0700 Subject: [PATCH 75/87] Fix docs header (#979) --- docs/griptape-framework/drivers/web-search-drivers.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/griptape-framework/drivers/web-search-drivers.md b/docs/griptape-framework/drivers/web-search-drivers.md index 18ba1e21c..b06c8d0a5 100644 --- a/docs/griptape-framework/drivers/web-search-drivers.md +++ b/docs/griptape-framework/drivers/web-search-drivers.md @@ -4,7 +4,9 @@ Web Search Drivers can be used to search for links from a search query. They are * `search()` searches the web and returns a [ListArtifact](../../reference/griptape/artifacts/list_artifact.md) that contains JSON-serializable [TextArtifact](../../reference/griptape/artifacts/text_artifact.md)s with the search results. -## Google +## Vector Store Drivers + +### Google The [GoogleWebSearchDriver](../../reference/griptape/drivers/web_search/google_web_search_driver.md) uses the [Google Custom Search JSON API](https://developers.google.com/custom-search/v1/reference/rest/v1/cse/list) for web searching. @@ -44,7 +46,7 @@ agent = Agent( agent.run("Give me some websites with information about AI frameworks.") ``` -## DuckDuckGo +### DuckDuckGo !!! info This driver requires the `drivers-web-search-duckduckgo` [extra](../index.md#extras). From 71a499d72b98a4260c4bdc654afb127ce8f0c4b2 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 16 Jul 2024 15:04:47 -0700 Subject: [PATCH 76/87] Remove unnecessary dependencies in extras (#989) --- CHANGELOG.md | 2 + poetry.lock | 155 +++++++++++++++++++++++++++++++++++-------------- pyproject.toml | 8 +-- 3 files changed, 115 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 151a2199a..6483152d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: `BaseVectorStoreDriver.query` optional arguments are now keyword-only arguments. - **BREAKING**: `EventListener.publish_event`'s `flush` argument is now a keyword-only argument. - **BREAKING**: `BaseEventListenerDriver.publish_event`'s `flush` argument is now a keyword-only argument. +- Removed unnecessary `transformers` dependency in `drivers-prompt-huggingface` extra. +- Removed unnecessary `huggingface-hub` dependency in `drivers-prompt-huggingface-pipeline` extra. ### Fixed - Parameter `count` for `QdrantVectorStoreDriver.query` now optional as per documentation. diff --git a/poetry.lock b/poetry.lock index 8e11c84e5..d654c99f5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,5 +1,36 @@ # This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +[[package]] +name = "accelerate" +version = "0.32.1" +description = "Accelerate" +optional = true +python-versions = ">=3.8.0" +files = [ + {file = "accelerate-0.32.1-py3-none-any.whl", hash = "sha256:71fcf4be00872194071de561634268b71417d7f5b16b178e2fa76b6f117c52b0"}, + {file = "accelerate-0.32.1.tar.gz", hash = "sha256:3999acff0237cd0d4f9fd98b42d5a3163544777b53fc4f1eec886b77e992d177"}, +] + +[package.dependencies] +huggingface-hub = "*" +numpy = ">=1.17,<2.0.0" +packaging = ">=20.0" +psutil = "*" +pyyaml = "*" +safetensors = ">=0.3.1" +torch = ">=1.10.0" + +[package.extras] +deepspeed = ["deepspeed (<=0.14.0)"] +dev = ["bitsandbytes", "black (>=23.1,<24.0)", "datasets", "diffusers", "evaluate", "hf-doc-builder (>=0.3.0)", "parameterized", "pytest (>=7.2.0,<=8.0.0)", "pytest-subtests", "pytest-xdist", "rich", "ruff (>=0.2.1,<0.3.0)", "scikit-learn", "scipy", "timm", "torchpippy (>=0.2.0)", "tqdm", "transformers"] +quality = ["black (>=23.1,<24.0)", "hf-doc-builder (>=0.3.0)", "ruff (>=0.2.1,<0.3.0)"] +rich = ["rich"] +sagemaker = ["sagemaker"] +test-dev = ["bitsandbytes", "datasets", "diffusers", "evaluate", "scikit-learn", "scipy", "timm", "torchpippy (>=0.2.0)", "tqdm", "transformers"] +test-prod = ["parameterized", "pytest (>=7.2.0,<=8.0.0)", "pytest-subtests", "pytest-xdist"] +test-trackers = ["comet-ml", "dvclive", "tensorboard", "wandb"] +testing = ["bitsandbytes", "datasets", "diffusers", "evaluate", "parameterized", "pytest (>=7.2.0,<=8.0.0)", "pytest-subtests", "pytest-xdist", "scikit-learn", "scipy", "timm", "torchpippy (>=0.2.0)", "tqdm", "transformers"] + [[package]] name = "aiohttp" version = "3.9.5" @@ -3460,13 +3491,13 @@ files = [ [[package]] name = "nvidia-nvjitlink-cu12" -version = "12.4.127" +version = "12.5.82" description = "Nvidia JIT LTO Library" optional = true python-versions = ">=3" files = [ - {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-manylinux2014_x86_64.whl", hash = "sha256:06b3b9b25bf3f8af351d664978ca26a16d2c5127dbd53c0497e28d1fb9611d57"}, - {file = "nvidia_nvjitlink_cu12-12.4.127-py3-none-win_amd64.whl", hash = "sha256:fd9020c501d27d135f983c6d3e244b197a7ccad769e34df53a42e276b0e25fa1"}, + {file = "nvidia_nvjitlink_cu12-12.5.82-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f9b37bc5c8cf7509665cb6ada5aaa0ce65618f2332b7d3e78e9790511f111212"}, + {file = "nvidia_nvjitlink_cu12-12.5.82-py3-none-win_amd64.whl", hash = "sha256:e782564d705ff0bf61ac3e1bf730166da66dd2fe9012f111ede5fc49b64ae697"}, ] [[package]] @@ -3936,6 +3967,35 @@ files = [ {file = "protobuf-4.25.3.tar.gz", hash = "sha256:25b5d0b42fd000320bd7830b349e3b696435f3b329810427a6bcce6a5492cc5c"}, ] +[[package]] +name = "psutil" +version = "6.0.0" +description = "Cross-platform lib for process and system monitoring in Python." +optional = true +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, + {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, + {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, + {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, + {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, + {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, + {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, + {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, + {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, + {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + [[package]] name = "psycopg2-binary" version = "2.9.9" @@ -5536,29 +5596,32 @@ files = [ [[package]] name = "sympy" -version = "1.12" +version = "1.13.0" description = "Computer algebra system (CAS) in Python" optional = true python-versions = ">=3.8" files = [ - {file = "sympy-1.12-py3-none-any.whl", hash = "sha256:c3588cd4295d0c0f603d0f2ae780587e64e2efeedb3521e46b9bb1d08d184fa5"}, - {file = "sympy-1.12.tar.gz", hash = "sha256:ebf595c8dac3e0fdc4152c51878b498396ec7f30e7a914d6071e674d49420fb8"}, + {file = "sympy-1.13.0-py3-none-any.whl", hash = "sha256:6b0b32a4673fb91bd3cac3b55406c8e01d53ae22780be467301cc452f6680c92"}, + {file = "sympy-1.13.0.tar.gz", hash = "sha256:3b6af8f4d008b9a1a6a4268b335b984b23835f26d1d60b0526ebc71d48a25f57"}, ] [package.dependencies] -mpmath = ">=0.19" +mpmath = ">=1.1.0,<1.4" + +[package.extras] +dev = ["hypothesis (>=6.70.0)", "pytest (>=7.1.0)"] [[package]] name = "tbb" -version = "2021.12.0" +version = "2021.13.0" description = "Intel® oneAPI Threading Building Blocks (oneTBB)" optional = true python-versions = "*" files = [ - {file = "tbb-2021.12.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:f2cc9a7f8ababaa506cbff796ce97c3bf91062ba521e15054394f773375d81d8"}, - {file = "tbb-2021.12.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:a925e9a7c77d3a46ae31c34b0bb7f801c4118e857d137b68f68a8e458fcf2bd7"}, - {file = "tbb-2021.12.0-py3-none-win32.whl", hash = "sha256:b1725b30c174048edc8be70bd43bb95473f396ce895d91151a474d0fa9f450a8"}, - {file = "tbb-2021.12.0-py3-none-win_amd64.whl", hash = "sha256:fc2772d850229f2f3df85f1109c4844c495a2db7433d38200959ee9265b34789"}, + {file = "tbb-2021.13.0-py2.py3-none-manylinux1_i686.whl", hash = "sha256:a2567725329639519d46d92a2634cf61e76601dac2f777a05686fea546c4fe4f"}, + {file = "tbb-2021.13.0-py2.py3-none-manylinux1_x86_64.whl", hash = "sha256:aaf667e92849adb012b8874d6393282afc318aca4407fc62f912ee30a22da46a"}, + {file = "tbb-2021.13.0-py3-none-win32.whl", hash = "sha256:6669d26703e9943f6164c6407bd4a237a45007e79b8d3832fe6999576eaaa9ef"}, + {file = "tbb-2021.13.0-py3-none-win_amd64.whl", hash = "sha256:3528a53e4bbe64b07a6112b4c5a00ff3c61924ee46c9c68e004a1ac7ad1f09c3"}, ] [[package]] @@ -5790,31 +5853,31 @@ files = [ [[package]] name = "torch" -version = "2.3.0" +version = "2.3.1" description = "Tensors and Dynamic neural networks in Python with strong GPU acceleration" optional = true python-versions = ">=3.8.0" files = [ - {file = "torch-2.3.0-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:d8ea5a465dbfd8501f33c937d1f693176c9aef9d1c1b0ca1d44ed7b0a18c52ac"}, - {file = "torch-2.3.0-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:09c81c5859a5b819956c6925a405ef1cdda393c9d8a01ce3851453f699d3358c"}, - {file = "torch-2.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:1bf023aa20902586f614f7682fedfa463e773e26c58820b74158a72470259459"}, - {file = "torch-2.3.0-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:758ef938de87a2653bba74b91f703458c15569f1562bf4b6c63c62d9c5a0c1f5"}, - {file = "torch-2.3.0-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:493d54ee2f9df100b5ce1d18c96dbb8d14908721f76351e908c9d2622773a788"}, - {file = "torch-2.3.0-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:bce43af735c3da16cc14c7de2be7ad038e2fbf75654c2e274e575c6c05772ace"}, - {file = "torch-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:729804e97b7cf19ae9ab4181f91f5e612af07956f35c8b2c8e9d9f3596a8e877"}, - {file = "torch-2.3.0-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:d24e328226d8e2af7cf80fcb1d2f1d108e0de32777fab4aaa2b37b9765d8be73"}, - {file = "torch-2.3.0-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:b0de2bdc0486ea7b14fc47ff805172df44e421a7318b7c4d92ef589a75d27410"}, - {file = "torch-2.3.0-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:a306c87a3eead1ed47457822c01dfbd459fe2920f2d38cbdf90de18f23f72542"}, - {file = "torch-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:f9b98bf1a3c8af2d4c41f0bf1433920900896c446d1ddc128290ff146d1eb4bd"}, - {file = "torch-2.3.0-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:dca986214267b34065a79000cee54232e62b41dff1ec2cab9abc3fc8b3dee0ad"}, - {file = "torch-2.3.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:20572f426965dd8a04e92a473d7e445fa579e09943cc0354f3e6fef6130ce061"}, - {file = "torch-2.3.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:e65ba85ae292909cde0dde6369826d51165a3fc8823dc1854cd9432d7f79b932"}, - {file = "torch-2.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:5515503a193781fd1b3f5c474e89c9dfa2faaa782b2795cc4a7ab7e67de923f6"}, - {file = "torch-2.3.0-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:6ae9f64b09516baa4ef890af0672dc981c20b1f0d829ce115d4420a247e88fba"}, - {file = "torch-2.3.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:cd0dc498b961ab19cb3f8dbf0c6c50e244f2f37dbfa05754ab44ea057c944ef9"}, - {file = "torch-2.3.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:e05f836559251e4096f3786ee99f4a8cbe67bc7fbedba8ad5e799681e47c5e80"}, - {file = "torch-2.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:4fb27b35dbb32303c2927da86e27b54a92209ddfb7234afb1949ea2b3effffea"}, - {file = "torch-2.3.0-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:760f8bedff506ce9e6e103498f9b1e9e15809e008368594c3a66bf74a8a51380"}, + {file = "torch-2.3.1-cp310-cp310-manylinux1_x86_64.whl", hash = "sha256:605a25b23944be5ab7c3467e843580e1d888b8066e5aaf17ff7bf9cc30001cc3"}, + {file = "torch-2.3.1-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:f2357eb0965583a0954d6f9ad005bba0091f956aef879822274b1bcdb11bd308"}, + {file = "torch-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:32b05fe0d1ada7f69c9f86c14ff69b0ef1957a5a54199bacba63d22d8fab720b"}, + {file = "torch-2.3.1-cp310-none-macosx_11_0_arm64.whl", hash = "sha256:7c09a94362778428484bcf995f6004b04952106aee0ef45ff0b4bab484f5498d"}, + {file = "torch-2.3.1-cp311-cp311-manylinux1_x86_64.whl", hash = "sha256:b2ec81b61bb094ea4a9dee1cd3f7b76a44555375719ad29f05c0ca8ef596ad39"}, + {file = "torch-2.3.1-cp311-cp311-manylinux2014_aarch64.whl", hash = "sha256:490cc3d917d1fe0bd027057dfe9941dc1d6d8e3cae76140f5dd9a7e5bc7130ab"}, + {file = "torch-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:5802530783bd465fe66c2df99123c9a54be06da118fbd785a25ab0a88123758a"}, + {file = "torch-2.3.1-cp311-none-macosx_11_0_arm64.whl", hash = "sha256:a7dd4ed388ad1f3d502bf09453d5fe596c7b121de7e0cfaca1e2017782e9bbac"}, + {file = "torch-2.3.1-cp312-cp312-manylinux1_x86_64.whl", hash = "sha256:a486c0b1976a118805fc7c9641d02df7afbb0c21e6b555d3bb985c9f9601b61a"}, + {file = "torch-2.3.1-cp312-cp312-manylinux2014_aarch64.whl", hash = "sha256:224259821fe3e4c6f7edf1528e4fe4ac779c77addaa74215eb0b63a5c474d66c"}, + {file = "torch-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:e5fdccbf6f1334b2203a61a0e03821d5845f1421defe311dabeae2fc8fbeac2d"}, + {file = "torch-2.3.1-cp312-none-macosx_11_0_arm64.whl", hash = "sha256:3c333dc2ebc189561514eda06e81df22bf8fb64e2384746b2cb9f04f96d1d4c8"}, + {file = "torch-2.3.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:07e9ba746832b8d069cacb45f312cadd8ad02b81ea527ec9766c0e7404bb3feb"}, + {file = "torch-2.3.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:462d1c07dbf6bb5d9d2f3316fee73a24f3d12cd8dacf681ad46ef6418f7f6626"}, + {file = "torch-2.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:ff60bf7ce3de1d43ad3f6969983f321a31f0a45df3690921720bcad6a8596cc4"}, + {file = "torch-2.3.1-cp38-none-macosx_11_0_arm64.whl", hash = "sha256:bee0bd33dc58aa8fc8a7527876e9b9a0e812ad08122054a5bff2ce5abf005b10"}, + {file = "torch-2.3.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:aaa872abde9a3d4f91580f6396d54888620f4a0b92e3976a6034759df4b961ad"}, + {file = "torch-2.3.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:3d7a7f7ef21a7520510553dc3938b0c57c116a7daee20736a9e25cbc0e832bdc"}, + {file = "torch-2.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:4777f6cefa0c2b5fa87223c213e7b6f417cf254a45e5829be4ccd1b2a4ee1011"}, + {file = "torch-2.3.1-cp39-none-macosx_11_0_arm64.whl", hash = "sha256:2bb5af780c55be68fe100feb0528d2edebace1d55cb2e351de735809ba7391eb"}, ] [package.dependencies] @@ -5835,7 +5898,7 @@ nvidia-cusparse-cu12 = {version = "12.1.0.106", markers = "platform_system == \" nvidia-nccl-cu12 = {version = "2.20.5", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} nvidia-nvtx-cu12 = {version = "12.1.105", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\""} sympy = "*" -triton = {version = "2.3.0", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and python_version < \"3.12\""} +triton = {version = "2.3.1", markers = "platform_system == \"Linux\" and platform_machine == \"x86_64\" and python_version < \"3.12\""} typing-extensions = ">=4.8.0" [package.extras] @@ -5913,6 +5976,7 @@ files = [ ] [package.dependencies] +accelerate = {version = ">=0.21.0", optional = true, markers = "extra == \"torch\""} filelock = "*" huggingface-hub = ">=0.19.3,<1.0" numpy = ">=1.17" @@ -5922,6 +5986,7 @@ regex = "!=2019.12.17" requests = "*" safetensors = ">=0.4.1" tokenizers = ">=0.14,<0.19" +torch = {version = "*", optional = true, markers = "extra == \"torch\""} tqdm = ">=4.27" [package.extras] @@ -5971,17 +6036,17 @@ vision = ["Pillow (>=10.0.1,<=15.0)"] [[package]] name = "triton" -version = "2.3.0" +version = "2.3.1" description = "A language and compiler for custom Deep Learning operations" optional = true python-versions = "*" files = [ - {file = "triton-2.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ce4b8ff70c48e47274c66f269cce8861cf1dc347ceeb7a67414ca151b1822d8"}, - {file = "triton-2.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c3d9607f85103afdb279938fc1dd2a66e4f5999a58eb48a346bd42738f986dd"}, - {file = "triton-2.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:218d742e67480d9581bafb73ed598416cc8a56f6316152e5562ee65e33de01c0"}, - {file = "triton-2.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:381ec6b3dac06922d3e4099cfc943ef032893b25415de295e82b1a82b0359d2c"}, - {file = "triton-2.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:038e06a09c06a164fef9c48de3af1e13a63dc1ba3c792871e61a8e79720ea440"}, - {file = "triton-2.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d8f636e0341ac348899a47a057c3daea99ea7db31528a225a3ba4ded28ccc65"}, + {file = "triton-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c84595cbe5e546b1b290d2a58b1494df5a2ef066dd890655e5b8a8a92205c33"}, + {file = "triton-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9d64ae33bcb3a7a18081e3a746e8cf87ca8623ca13d2c362413ce7a486f893e"}, + {file = "triton-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eaf80e8761a9e3498aa92e7bf83a085b31959c61f5e8ac14eedd018df6fccd10"}, + {file = "triton-2.3.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b13bf35a2b659af7159bf78e92798dc62d877aa991de723937329e2d382f1991"}, + {file = "triton-2.3.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:63381e35ded3304704ea867ffde3b7cfc42c16a55b3062d41e017ef510433d66"}, + {file = "triton-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d968264523c7a07911c8fb51b4e0d1b920204dae71491b1fe7b01b62a31e124"}, ] [package.dependencies] @@ -6464,7 +6529,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] @@ -6482,8 +6547,8 @@ drivers-prompt-amazon-sagemaker = ["boto3", "transformers"] drivers-prompt-anthropic = ["anthropic"] drivers-prompt-cohere = ["cohere"] drivers-prompt-google = ["google-generativeai"] -drivers-prompt-huggingface = ["huggingface-hub", "transformers"] -drivers-prompt-huggingface-pipeline = ["huggingface-hub", "torch", "transformers"] +drivers-prompt-huggingface = ["huggingface-hub"] +drivers-prompt-huggingface-pipeline = ["transformers"] drivers-prompt-ollama = ["ollama"] drivers-rerank-cohere = ["cohere"] drivers-sql-postgres = ["pgvector", "psycopg2-binary"] @@ -6509,4 +6574,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "09d5503da93cfcba7fdb3cc462395d5a2754bace3cee33feef9002b5904d5493" +content-hash = "a49e3177bd216b5af2ffe2f213d1e2d8081f23ef33e4c71ecc16c673287823fa" diff --git a/pyproject.toml b/pyproject.toml index 807a2560e..fabce497e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -32,7 +32,7 @@ requests = "^2.32.0" # drivers cohere = { version = "^5.5.4", optional = true } anthropic = { version = "^0.29.0", optional = true } -transformers = { version = "^4.39.3", optional = true } +transformers = { version = "^4.39.3", optional = true, extras=["torch"] } huggingface-hub = { version = ">=0.13", optional = true } boto3 = { version = "^1.34.119", optional = true } sqlalchemy-redshift = { version = "*", optional = true } @@ -51,7 +51,6 @@ beautifulsoup4 = {version = "^4.12.3", optional = true} markdownify = {version = "^0.11.6", optional = true} voyageai = {version = "^0.2.1", optional = true} elevenlabs = {version = "^1.1.2", optional = true} -torch = {version = "^2.3.0", optional = true} qdrant-client = { version = ">=1.9.1", optional = true } pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} @@ -67,8 +66,8 @@ filetype = {version = "^1.2", optional = true} [tool.poetry.extras] drivers-prompt-cohere = ["cohere"] drivers-prompt-anthropic = ["anthropic"] -drivers-prompt-huggingface = ["huggingface-hub", "transformers"] -drivers-prompt-huggingface-pipeline = ["huggingface-hub", "transformers", "torch"] +drivers-prompt-huggingface = ["huggingface-hub"] +drivers-prompt-huggingface-pipeline = ["transformers"] drivers-prompt-amazon-bedrock = ["boto3", "anthropic"] drivers-prompt-amazon-sagemaker = ["boto3", "transformers"] drivers-prompt-google = ["google-generativeai"] @@ -140,7 +139,6 @@ all = [ "markdownify", "voyageai", "elevenlabs", - "torch", "pusher", "ollama", "duckduckgo-search", From 7c13601c1cd1c547f2a0f5b1e24c837998194f2f Mon Sep 17 00:00:00 2001 From: dylanholmes <4370153+dylanholmes@users.noreply.github.com> Date: Tue, 16 Jul 2024 16:31:36 -0700 Subject: [PATCH 77/87] Add default for GriptapeCloudEventListenerDriver.api_key (#990) --- .github/workflows/docs-integration-tests.yml | 1 + CHANGELOG.md | 1 + .../drivers/event-listener-drivers.md | 12 ++++++------ .../griptape_cloud_event_listener_driver.py | 2 +- griptape/tools/calculator/tool.py | 2 +- ...est_griptape_cloud_event_listener_driver.py | 18 ++++++++++++++++-- 6 files changed, 26 insertions(+), 10 deletions(-) diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index 241c4a2ef..ce30f83bb 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -72,6 +72,7 @@ jobs: GOOGLE_AUTH_URI: ${{ secrets.INTEG_GOOGLE_AUTH_URI }} GOOGLE_TOKEN_URI: ${{ secrets.INTEG_GOOGLE_TOKEN_URI }} GOOGLE_AUTH_PROVIDER_X509_CERT_URL: ${{ secrets.INTEG_GOOGLE_AUTH_PROVIDER_X509_CERT_URL }} + GT_CLOUD_API_KEY: ${{ secrets.INTEG_GRIPTAPE_CLOUD_API_KEY }} GRIPTAPE_CLOUD_API_KEY: ${{ secrets.INTEG_GRIPTAPE_CLOUD_API_KEY }} GRIPTAPE_CLOUD_STRUCTURE_ID: ${{ secrets.INTEG_GRIPTAPE_CLOUD_STRUCTURE_ID }} GRIPTAPE_CLOUD_BASE_URL: ${{ secrets.INTEG_GRIPTAPE_CLOUD_BASE_URL }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6483152d6..d146d815a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Native function calling support to `OpenAiChatPromptDriver`, `AzureOpenAiChatPromptDriver`, `AnthropicPromptDriver`, `AmazonBedrockPromptDriver`, `GooglePromptDriver`, and `CoherePromptDriver`. - `OllamaEmbeddingDriver` for generating embeddings with Ollama. - `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. +- `GriptapeCloudEventListenerDriver.api_key` defaults to the value in the `GT_CLOUD_API_KEY` environment variable. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifacts` optional arguments are now keyword-only arguments. diff --git a/docs/griptape-framework/drivers/event-listener-drivers.md b/docs/griptape-framework/drivers/event-listener-drivers.md index 4a85bc9a4..5e73f1a09 100644 --- a/docs/griptape-framework/drivers/event-listener-drivers.md +++ b/docs/griptape-framework/drivers/event-listener-drivers.md @@ -50,9 +50,9 @@ from griptape.drivers import GriptapeCloudEventListenerDriver from griptape.events import FinishStructureRunEvent from griptape.artifacts import TextArtifact -event_driver = GriptapeCloudEventListenerDriver( - api_key=os.environ["GRIPTAPE_CLOUD_API_KEY"] -) +# By default, GriptapeCloudEventListenerDriver uses the api key provided +# in the GT_CLOUD_API_KEY environment variable. +event_driver = GriptapeCloudEventListenerDriver() done_event = FinishStructureRunEvent( output_task_input=TextArtifact("Just started!"), @@ -173,9 +173,9 @@ agent = Agent( event_listeners=[ EventListener( event_types=[FinishStructureRunEvent], - driver=GriptapeCloudEventListenerDriver( - api_key=os.environ["GRIPTAPE_CLOUD_API_KEY"], - ), + # By default, GriptapeCloudEventListenerDriver uses the api key provided + # in the GT_CLOUD_API_KEY environment variable. + driver=GriptapeCloudEventListenerDriver(), ), ], ) diff --git a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py index 2e208d786..cf9dd7bd2 100644 --- a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py +++ b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py @@ -24,7 +24,7 @@ class GriptapeCloudEventListenerDriver(BaseEventListenerDriver): default=Factory(lambda: os.getenv("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")), kw_only=True, ) - api_key: str = field(kw_only=True) + api_key: str = field(default=Factory(lambda: os.getenv("GT_CLOUD_API_KEY")), kw_only=True) headers: dict = field( default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True, diff --git a/griptape/tools/calculator/tool.py b/griptape/tools/calculator/tool.py index 141d1a333..e8fcb1ed4 100644 --- a/griptape/tools/calculator/tool.py +++ b/griptape/tools/calculator/tool.py @@ -21,7 +21,7 @@ class Calculator(BaseTool): }, ) def calculate(self, params: dict) -> BaseArtifact: - import numexpr + import numexpr # pyright: ignore[reportMissingImports] try: expression = params["values"]["expression"] diff --git a/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py b/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py index b651841ca..5db78b76f 100644 --- a/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py @@ -19,9 +19,23 @@ def mock_post(self, mocker): @pytest.fixture() def driver(self): - os.environ["GT_CLOUD_BASE_URL"] = "https://cloud123.griptape.ai" + environ = { + "GT_CLOUD_BASE_URL": "https://cloud123.griptape.ai", + "GT_CLOUD_API_KEY": "foo bar", + "GT_CLOUD_STRUCTURE_RUN_ID": "bar baz", + } + original_environ = {} + for key, value in environ.items(): + original_environ[key] = os.environ.get(key) + os.environ[key] = value - return GriptapeCloudEventListenerDriver(api_key="foo bar", structure_run_id="bar baz") + yield GriptapeCloudEventListenerDriver() + + for key, value in original_environ.items(): + if value is None: + del os.environ[key] + else: + os.environ[key] = value def test_init(self, driver): assert driver From 8026409cee885bcf0a038605679ad2077270d0db Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 17 Jul 2024 10:50:26 -0700 Subject: [PATCH 78/87] Fix Windows-specific issues (#992) --- .github/actions/init-environment/action.yml | 2 +- .github/workflows/unit-tests.yml | 22 ++++++++++++++- CHANGELOG.md | 1 + .../amazon_s3_file_manager_driver.py | 27 +++++++++++++++---- tests/unit/artifacts/test_blob_artifact.py | 5 +++- .../test_amazon_s3_file_manager_driver.py | 12 ++++----- .../test_local_file_manager_driver.py | 21 +++++++-------- tests/unit/utils/test_command_runner.py | 2 +- tests/unit/utils/test_file_utils.py | 2 -- 9 files changed, 65 insertions(+), 29 deletions(-) diff --git a/.github/actions/init-environment/action.yml b/.github/actions/init-environment/action.yml index 686f57e34..0d9ad94fc 100644 --- a/.github/actions/init-environment/action.yml +++ b/.github/actions/init-environment/action.yml @@ -32,7 +32,7 @@ runs: - name: Activate venv run: | - source .venv/bin/activate + source $VENV echo PATH=$PATH >> $GITHUB_ENV shell: bash diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index d24a0d541..946af9a51 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -11,7 +11,7 @@ concurrency: cancel-in-progress: true jobs: - test: + test-ubuntu: runs-on: ubuntu-latest strategy: fail-fast: false @@ -24,3 +24,23 @@ jobs: uses: ./.github/actions/init-environment - name: Run unit tests run: make test/unit + test-windows: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.9"] + defaults: + run: + shell: bash + steps: + - name: Checkout actions + uses: actions/checkout@v3 + - name: Init environment + uses: ./.github/actions/init-environment + - name: Run unit tests + # TODO: make test/unit fails with the following error: + # process_begin: CreateProcess(NULL, poetry run pytest -n auto tests/unit, ...) failed. + # make (e=2): The system cannot find the file specified. + # make: *** [Makefile:24: test/unit] Error 2 + run: poetry run pytest -n auto tests/unit diff --git a/CHANGELOG.md b/CHANGELOG.md index d146d815a..67d7fd92f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Parameter `count` for `QdrantVectorStoreDriver.query` now optional as per documentation. +- Path issues on Windows with `LocalFileManagerDriver` and `AmazonS3FileManagerDriver`. ## [0.28.2] - 2024-07-12 ### Fixed diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index 4623f8231..01eb1e21f 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -1,7 +1,5 @@ from __future__ import annotations -import os -from pathlib import Path from typing import TYPE_CHECKING, Any from attrs import Attribute, Factory, define, field @@ -33,7 +31,7 @@ class AmazonS3FileManagerDriver(BaseFileManagerDriver): @workdir.validator # pyright: ignore[reportAttributeAccessIssue] def validate_workdir(self, _: Attribute, workdir: str) -> None: - if not Path(workdir).is_absolute(): + if not workdir.startswith("/"): raise ValueError("Workdir must be an absolute path") def try_list_files(self, path: str) -> list[str]: @@ -70,11 +68,13 @@ def try_save_file(self, path: str, value: bytes) -> None: def _to_full_key(self, path: str) -> str: path = path.lstrip("/") - full_key = os.path.join(self.workdir, path) + full_key = f"{self.workdir}/{path}" # Need to keep the trailing slash if it was there, # because it means the path is a directory. ended_with_slash = path.endswith("/") - full_key = os.path.normpath(full_key) + + full_key = self._normpath(full_key) + if ended_with_slash: full_key += "/" return full_key.lstrip("/") @@ -126,3 +126,20 @@ def _is_a_directory(self, full_key: str) -> bool: raise e return False + + def _normpath(self, path: str) -> str: + unix_path = path.replace("\\", "/") + parts = unix_path.split("/") + stack = [] + + for part in parts: + if part == "" or part == ".": + continue + if part == "..": + if stack: + stack.pop() + else: + stack.append(part) + + normalized_path = "/".join(stack) + return normalized_path diff --git a/tests/unit/artifacts/test_blob_artifact.py b/tests/unit/artifacts/test_blob_artifact.py index a50a673f4..3d88d5793 100644 --- a/tests/unit/artifacts/test_blob_artifact.py +++ b/tests/unit/artifacts/test_blob_artifact.py @@ -1,4 +1,5 @@ import base64 +import os import pytest @@ -32,7 +33,9 @@ def test_to_dict(self): assert BlobArtifact(b"foobar", name="foobar.txt", dir_name="foo").to_dict()["name"] == "foobar.txt" def test_full_path_with_path(self): - assert BlobArtifact(b"foobar", name="foobar.txt", dir_name="foo").full_path == "foo/foobar.txt" + assert BlobArtifact(b"foobar", name="foobar.txt", dir_name="foo").full_path == os.path.normpath( + "foo/foobar.txt" + ) def test_full_path_without_path(self): assert BlobArtifact(b"foobar", name="foobar.txt").full_path == "foobar.txt" diff --git a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py index cad76a7d6..3af9eb4cc 100644 --- a/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_amazon_s3_file_manager_driver.py @@ -223,7 +223,7 @@ def test_save_file(self, workdir, path, content, driver, get_s3_value): assert isinstance(result, InfoArtifact) assert result.value == "Successfully saved file" - expected_s3_key = os.path.join(workdir, path).lstrip("/") + expected_s3_key = f"{workdir}/{path}".lstrip("/") content_str = content if isinstance(content, str) else content.decode() assert get_s3_value(expected_s3_key) == content_str @@ -258,11 +258,11 @@ def test_save_file_with_encoding(self, session, bucket, get_s3_value): driver = AmazonS3FileManagerDriver( session=session, bucket=bucket, default_loader=TextLoader(encoding="utf-8"), loaders={}, workdir=workdir ) - path = os.path.join("test", "foobar.txt") + path = "test/foobar.txt" result = driver.save_file(path, "foobar") - expected_s3_key = os.path.join(workdir, path).lstrip("/") + expected_s3_key = f"{workdir}/{path}".lstrip("/") assert get_s3_value(expected_s3_key) == "foobar" assert result.value == "Successfully saved file" @@ -271,18 +271,18 @@ def test_save_and_load_file_with_encoding(self, session, bucket, get_s3_value): driver = AmazonS3FileManagerDriver( session=session, bucket=bucket, loaders={"txt": TextLoader(encoding="ascii")}, workdir=workdir ) - path = os.path.join("test", "foobar.txt") + path = "test/foobar.txt" result = driver.save_file(path, "foobar") - expected_s3_key = os.path.join(workdir, path).lstrip("/") + expected_s3_key = f"{workdir}/{path}".lstrip("/") assert get_s3_value(expected_s3_key) == "foobar" assert result.value == "Successfully saved file" driver = AmazonS3FileManagerDriver( session=session, bucket=bucket, default_loader=TextLoader(encoding="ascii"), loaders={}, workdir=workdir ) - path = os.path.join("test", "foobar.txt") + path = "test/foobar.txt" result = driver.load_file(path) diff --git a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py index ec9963b49..23f9ef535 100644 --- a/tests/unit/drivers/file_manager/test_local_file_manager_driver.py +++ b/tests/unit/drivers/file_manager/test_local_file_manager_driver.py @@ -98,7 +98,7 @@ def test_validate_workdir(self): ) def test_list_files(self, workdir, path, expected, temp_dir, driver): # Treat the workdir as an absolute path, but modify it to be relative to the temp_dir. - driver.workdir = os.path.join(temp_dir, os.path.abspath(workdir).lstrip("/")) + driver.workdir = self._to_driver_workdir(temp_dir, workdir) artifact = driver.list_files(path) @@ -121,7 +121,7 @@ def test_list_files(self, workdir, path, expected, temp_dir, driver): ) def test_list_files_failure(self, workdir, path, expected, temp_dir, driver): # Treat the workdir as an absolute path, but modify it to be relative to the temp_dir. - driver.workdir = os.path.join(temp_dir, os.path.abspath(workdir).lstrip("/")) + driver.workdir = self._to_driver_workdir(temp_dir, workdir) artifact = driver.list_files(path) @@ -155,7 +155,7 @@ def test_load_file(self, driver: LocalFileManagerDriver): ) def test_load_file_failure(self, workdir, path, expected, temp_dir, driver): # Treat the workdir as an absolute path, but modify it to be relative to the temp_dir. - driver.workdir = os.path.join(temp_dir, os.path.abspath(workdir).lstrip("/")) + driver.workdir = self._to_driver_workdir(temp_dir, workdir) artifact = driver.load_file(path) @@ -194,7 +194,7 @@ def test_load_file_with_encoding_failure(self): ) def test_save_file(self, workdir, path, content, temp_dir, driver): # Treat the workdir as an absolute path, but modify it to be relative to the temp_dir. - driver.workdir = os.path.join(temp_dir, os.path.abspath(workdir).lstrip("/")) + driver.workdir = self._to_driver_workdir(temp_dir, workdir) result = driver.save_file(path, content) @@ -223,7 +223,7 @@ def test_save_file(self, workdir, path, content, temp_dir, driver): ) def test_save_file_failure(self, workdir, path, expected, temp_dir, driver): # Treat the workdir as an absolute path, but modify it to be relative to the temp_dir. - driver.workdir = os.path.join(temp_dir, os.path.abspath(workdir).lstrip("/")) + driver.workdir = self._to_driver_workdir(temp_dir, workdir) artifact = driver.save_file(path, "foobar") @@ -251,10 +251,7 @@ def test_save_and_load_file_with_encoding(self, temp_dir): assert len(result.value) == 1 assert isinstance(result.value[0], TextArtifact) - def test_chrdir_getcwd(self, temp_dir): - os.chdir(temp_dir) - file_manager_1 = LocalFileManagerDriver() - assert file_manager_1.workdir.endswith(temp_dir) - os.chdir("/tmp") - file_manager_2 = LocalFileManagerDriver() - assert file_manager_2.workdir.endswith("/tmp") + def _to_driver_workdir(self, temp_dir, workdir): + # Treat the workdir as an absolute path, but modify it to be relative to the temp_dir. + root_relative_parts = Path(os.path.abspath(workdir)).parts[1:] + return os.path.join(temp_dir, Path(*root_relative_parts)) diff --git a/tests/unit/utils/test_command_runner.py b/tests/unit/utils/test_command_runner.py index 25b7fd8c3..4cf0bbeaa 100644 --- a/tests/unit/utils/test_command_runner.py +++ b/tests/unit/utils/test_command_runner.py @@ -3,4 +3,4 @@ class TestCommandRunner: def test_run(self): - assert CommandRunner().run("echo 'test'").value == "test" + assert "test" in CommandRunner().run("echo 'test'").value diff --git a/tests/unit/utils/test_file_utils.py b/tests/unit/utils/test_file_utils.py index de1882ef5..a9c122126 100644 --- a/tests/unit/utils/test_file_utils.py +++ b/tests/unit/utils/test_file_utils.py @@ -14,7 +14,6 @@ def test_load_file(self): file = utils.load_file(os.path.join(dirname, "../../resources/foobar-many.txt")) assert file.decode("utf-8").startswith("foobar foobar foobar") - assert len(file.decode("utf-8")) == 4563 def test_load_files(self): dirname = os.path.dirname(__file__) @@ -24,7 +23,6 @@ def test_load_files(self): assert len(files) == 2 test_file = files[utils.str_to_hash(sources[0])] - assert len(test_file) == 4563 assert test_file.decode("utf-8").startswith("foobar foobar foobar") small_file = files[utils.str_to_hash(sources[2])] From 7d263b9b9fc802ff67ff9273fa84bb20625d1bee Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 17 Jul 2024 11:07:03 -0700 Subject: [PATCH 79/87] Improve native tool name check (#968) Co-authored-by: dylanholmes <4370153+dylanholmes@users.noreply.github.com> --- griptape/tools/base_tool.py | 19 ++++++++++++++----- tests/unit/tools/test_base_tool.py | 11 +++++++++-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 60eb10cda..91b90e775 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -3,6 +3,7 @@ import inspect import logging import os +import re import subprocess import sys from abc import ABC @@ -204,15 +205,23 @@ def find_input_memory(self, memory_name: str) -> Optional[TaskMemory]: return None def to_native_tool_name(self, activity: Callable) -> str: - """Converts a Tool into to a native tool name. + """Converts a Tool's name and an Activity into to a native tool name. + + The native tool name is a combination of the Tool's name and the Activity's name. + The Tool's name may only contain letters and numbers, and the Activity's name may only contain letters, numbers, and underscores. Args: - activity: Activity to convert. + activity: Activity to convert Returns: str: Native tool name. """ - if "_" in self.name: - raise ValueError("Tool name can't contain underscores when using native tools.") + tool_name = self.name + if re.match(r"^[a-zA-Z0-9]+$", tool_name) is None: + raise ValueError("Tool name can only contain letters and numbers.") + + activity_name = self.activity_name(activity) + if re.match(r"^[a-zA-Z0-9_]+$", activity_name) is None: + raise ValueError("Activity name can only contain letters, numbers, and underscores.") - return f"{self.name}_{self.activity_name(activity)}" + return f"{tool_name}_{activity_name}" diff --git a/tests/unit/tools/test_base_tool.py b/tests/unit/tools/test_base_tool.py index a4d4097c1..9c1764837 100644 --- a/tests/unit/tools/test_base_tool.py +++ b/tests/unit/tools/test_base_tool.py @@ -249,11 +249,18 @@ def test_activity_schemas(self, tool): assert tool_schema == self.TARGET_TOOL_SCHEMA - def test_to_native_tool_name(self, tool): + def test_to_native_tool_name(self, tool, mocker): tool = MockTool() assert tool.to_native_tool_name(tool.test) == "MockTool_test" + # Bad name tool.name = "mock_tool" - with pytest.raises(ValueError): + with pytest.raises(ValueError, match="Tool name"): tool.to_native_tool_name(tool.foo) + + # Bad activity name + mocker.patch.object(tool, "activity_name", return_value="foo^bar") + tool.name = "MockTool" + with pytest.raises(ValueError, match="Activity name"): + tool.to_native_tool_name(tool.test) From 33469efd7012bd65e745e14df59928e6523e288f Mon Sep 17 00:00:00 2001 From: dylanholmes <4370153+dylanholmes@users.noreply.github.com> Date: Wed, 17 Jul 2024 12:47:32 -0700 Subject: [PATCH 80/87] Add observability (#991) --- CHANGELOG.md | 6 + .../drivers/observability-drivers.md | 192 ++++++++++++ .../structures/observability.md | 57 ++++ griptape/common/__init__.py | 3 + griptape/common/observable.py | 77 +++++ griptape/drivers/__init__.py | 9 + .../griptape_cloud_event_listener_driver.py | 12 + griptape/drivers/observability/__init__.py | 0 .../base_observability_driver.py | 31 ++ .../griptape_cloud_observability_driver.py | 104 +++++++ .../no_op_observability_driver.py | 19 ++ .../open_telemetry_observability_driver.py | 86 ++++++ .../prompt/amazon_bedrock_prompt_driver.py | 3 + ...mazon_sagemaker_jumpstart_prompt_driver.py | 4 +- .../drivers/prompt/anthropic_prompt_driver.py | 3 + griptape/drivers/prompt/base_prompt_driver.py | 2 + .../drivers/prompt/cohere_prompt_driver.py | 3 + .../drivers/prompt/dummy_prompt_driver.py | 3 + .../drivers/prompt/google_prompt_driver.py | 3 + .../prompt/huggingface_hub_prompt_driver.py | 4 +- .../huggingface_pipeline_prompt_driver.py | 4 +- .../drivers/prompt/ollama_prompt_driver.py | 3 + .../prompt/openai_chat_prompt_driver.py | 3 + griptape/observability/__init__.py | 3 + griptape/observability/observability.py | 57 ++++ griptape/structures/agent.py | 2 + griptape/structures/pipeline.py | 2 + griptape/structures/structure.py | 4 + griptape/structures/workflow.py | 2 + griptape/tools/base_tool.py | 2 + poetry.lock | 228 +++++++++++++- pyproject.toml | 25 ++ tests/unit/common/test_observable.py | 238 +++++++++++++++ ...st_griptape_cloud_event_listener_driver.py | 27 +- tests/unit/drivers/observability/__init__.py | 0 ...est_griptape_cloud_observability_driver.py | 284 ++++++++++++++++++ .../test_no_op_observability_driver.py | 32 ++ ...est_open_telemetry_observability_driver.py | 197 ++++++++++++ tests/unit/observability/__init__.py | 0 .../unit/observability/test_observability.py | 50 +++ tests/utils/expected_spans.py | 86 ++++++ 41 files changed, 1864 insertions(+), 6 deletions(-) create mode 100644 docs/griptape-framework/drivers/observability-drivers.md create mode 100644 docs/griptape-framework/structures/observability.md create mode 100644 griptape/common/observable.py create mode 100644 griptape/drivers/observability/__init__.py create mode 100644 griptape/drivers/observability/base_observability_driver.py create mode 100644 griptape/drivers/observability/griptape_cloud_observability_driver.py create mode 100644 griptape/drivers/observability/no_op_observability_driver.py create mode 100644 griptape/drivers/observability/open_telemetry_observability_driver.py create mode 100644 griptape/observability/__init__.py create mode 100644 griptape/observability/observability.py create mode 100644 tests/unit/common/test_observable.py create mode 100644 tests/unit/drivers/observability/__init__.py create mode 100644 tests/unit/drivers/observability/test_griptape_cloud_observability_driver.py create mode 100644 tests/unit/drivers/observability/test_no_op_observability_driver.py create mode 100644 tests/unit/drivers/observability/test_open_telemetry_observability_driver.py create mode 100644 tests/unit/observability/__init__.py create mode 100644 tests/unit/observability/test_observability.py create mode 100644 tests/utils/expected_spans.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 67d7fd92f..f636f548a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `OllamaEmbeddingDriver` for generating embeddings with Ollama. - `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. - `GriptapeCloudEventListenerDriver.api_key` defaults to the value in the `GT_CLOUD_API_KEY` environment variable. +- `BaseObservabilityDriver` as the base class for all Observability Drivers. +- `DummyObservabilityDriver` as a no-op Observability Driver. +- `OpenTelemetryObservabilityDriver` for sending observability data to an open telemetry collector or vendor. +- `GriptapeCloudObservabilityDriver` for sending observability data to Griptape Cloud. +- `Observability` context manager for enabling observability and configuring which Observability Driver to use. +- `@observable` decorator for selecting which functions/methods to provide observability for. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifacts` optional arguments are now keyword-only arguments. diff --git a/docs/griptape-framework/drivers/observability-drivers.md b/docs/griptape-framework/drivers/observability-drivers.md new file mode 100644 index 000000000..8c2c5d2a5 --- /dev/null +++ b/docs/griptape-framework/drivers/observability-drivers.md @@ -0,0 +1,192 @@ +# Observability Drivers + +Observability Drivers are used by [Observability](../structures/observability.md) to send telemetry (metrics and traces) related to the execution of an LLM application. The telemetry can be used to monitor the application and to diagnose and troubleshoot issues. All Observability Drivers implement the following methods: + +* `__enter__()` sets up the Driver. +* `__exit__()` tears down the Driver. +* `observe()` wraps all functions and methods marked with the `@observable` decorator. At a bare minimum, implementations call the wrapped function and return its result (a no-op). This enables the Driver to generate telemetry related to the invocation's call arguments, return values, exceptions, latency, etc. + +## Griptape Cloud + +!!! info + This driver requires the `drivers-observability-griptape-cloud` [extra](../index.md#extras). + +The Griptape Cloud Observability Driver instruments `@observable` functions and methods with metrics and traces for use with the Griptape Cloud. + +!!! note + For the Griptape Cloud Observability Driver to function as intended, it must be run from within either a Managed Structure on Griptape Cloud + or locally via the [Skatepark Emulator](https://github.com/griptape-ai/griptape-cli?tab=readme-ov-file#skatepark-emulator). + +Here is an example of how to use the `GriptapeCloudObservabilityDriver` with the `Observability` context manager to send the telemetry to Griptape Cloud: + + +```python title="PYTEST_IGNORE" +from griptape.drivers import GriptapeCloudObservabilityDriver +from griptape.rules import Rule +from griptape.structures import Agent +from griptape.observability import Observability + +observability_driver = GriptapeCloudObservabilityDriver() + +with Observability(observability_driver=observability_driver): + agent = Agent(rules=[Rule("Output one word")]) + agent.run("Name an animal") +``` + + +## OpenTelemetry + +!!! info + This driver requires the `drivers-observability-opentelemetry` [extra](../index.md#extras). + +The [OpenTelemetry](https://opentelemetry.io/) Observability Driver instruments `@observable` functions and methods with metrics and traces for use with OpenTelemetry. You must configure a destination for the telemetry by providing a `SpanProcessor` to the Driver. + + +Here is an example of how to use the `OpenTelemetryObservabilityDriver` with the `Observability` context manager to output the telemetry directly to the console: + +```python title="PYTEST_IGNORE" +from griptape.drivers import OpenTelemetryObservabilityDriver +from griptape.rules import Rule +from griptape.structures import Agent +from griptape.observability import Observability +from opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor + +observability_driver = OpenTelemetryObservabilityDriver( + service_name="name-an-animal", + span_processor=BatchSpanProcessor(ConsoleSpanExporter()) +) + +with Observability(observability_driver=observability_driver): + agent = Agent(rules=[Rule("Output one word")]) + agent.run("Name an animal") +``` + +Output (only relevant because of use of `ConsoleSpanExporter`): +``` +[06/18/24 06:57:22] INFO PromptTask 2d8ef95bf817480188ae2f74e754308a + Input: Name an animal +[06/18/24 06:57:23] INFO PromptTask 2d8ef95bf817480188ae2f74e754308a + Output: Elephant +{ + "name": "Agent.before_run()", + "context": { + "trace_id": "0x4f3d72f7ff4e6a453f5c950fa097583e", + "span_id": "0x8cf827b375f6922f", + "trace_state": "[]" + }, + "kind": "SpanKind.INTERNAL", + "parent_id": "0x580276d16c584de3", + "start_time": "2024-06-18T13:57:22.640040Z", + "end_time": "2024-06-18T13:57:22.640822Z", + "status": { + "status_code": "OK" + }, + "attributes": {}, + "events": [], + "links": [], + "resource": { + "attributes": { + "service.name": "my-gt-app" + }, + "schema_url": "" + } +} +{ + "name": "Agent.try_run()", + "context": { + "trace_id": "0x4f3d72f7ff4e6a453f5c950fa097583e", + "span_id": "0x7191a27da608cbe7", + "trace_state": "[]" + }, + "kind": "SpanKind.INTERNAL", + "parent_id": "0x580276d16c584de3", + "start_time": "2024-06-18T13:57:22.640846Z", + "end_time": "2024-06-18T13:57:23.287311Z", + "status": { + "status_code": "OK" + }, + "attributes": {}, + "events": [], + "links": [], + "resource": { + "attributes": { + "service.name": "my-gt-app" + }, + "schema_url": "" + } +} +{ + "name": "Agent.after_run()", + "context": { + "trace_id": "0x4f3d72f7ff4e6a453f5c950fa097583e", + "span_id": "0x99824dd1bc842f66", + "trace_state": "[]" + }, + "kind": "SpanKind.INTERNAL", + "parent_id": "0x580276d16c584de3", + "start_time": "2024-06-18T13:57:23.287707Z", + "end_time": "2024-06-18T13:57:23.288666Z", + "status": { + "status_code": "OK" + }, + "attributes": {}, + "events": [], + "links": [], + "resource": { + "attributes": { + "service.name": "my-gt-app" + }, + "schema_url": "" + } +} +{ + "name": "Agent.run()", + "context": { + "trace_id": "0x4f3d72f7ff4e6a453f5c950fa097583e", + "span_id": "0x580276d16c584de3", + "trace_state": "[]" + }, + "kind": "SpanKind.INTERNAL", + "parent_id": "0xa42d36d9fff76325", + "start_time": "2024-06-18T13:57:22.640021Z", + "end_time": "2024-06-18T13:57:23.288694Z", + "status": { + "status_code": "OK" + }, + "attributes": {}, + "events": [], + "links": [], + "resource": { + "attributes": { + "service.name": "my-gt-app" + }, + "schema_url": "" + } +} +{ + "name": "main", + "context": { + "trace_id": "0x4f3d72f7ff4e6a453f5c950fa097583e", + "span_id": "0xa42d36d9fff76325", + "trace_state": "[]" + }, + "kind": "SpanKind.INTERNAL", + "parent_id": null, + "start_time": "2024-06-18T13:57:22.607005Z", + "end_time": "2024-06-18T13:57:23.288764Z", + "status": { + "status_code": "OK" + }, + "attributes": {}, + "events": [], + "links": [], + "resource": { + "attributes": { + "service.name": "my-gt-app" + }, + "schema_url": "" + } +} +``` + + diff --git a/docs/griptape-framework/structures/observability.md b/docs/griptape-framework/structures/observability.md new file mode 100644 index 000000000..5a9e9c51c --- /dev/null +++ b/docs/griptape-framework/structures/observability.md @@ -0,0 +1,57 @@ +## Overview + +The [Observability](../../reference/griptape/observability/observability.md) context manager sends telemetry (metrics and traces) for all functions and methods annotated with the `@observable` decorator to a destination of your choice. This is useful for monitoring and debugging your application. + +Observability is completely optional. To opt in, wrap your application code with the [Observability](../../reference/griptape/observability/observability.md) context manager, for example: + +```python title="PYTEST_IGNORE" +from griptape.drivers import GriptapeCloudObservabilityDriver +from griptape.structures import Agent +from griptape.observability import Observability + +observability_driver = GriptapeCloudObservabilityDriver() + +with Observability(observability_driver=observability_driver): + # Important! Only code within this block is subject to observability + agent = Agent() + agent.run("Name the five greatest rappers of all time") +``` + +!!! info + For available Drivers (and destinations), see [Observability Drivers](../drivers/observability-drivers.md). + +## Tracing Custom Code + +All functions and methods annotated with the `@observable` decorator will be traced when invoked within the context of the [Observability](../../reference/griptape/observability/observability.md) context manager, including functions and methods defined outside of the Griptape framework. Thus to trace custom code, you just need to add the `@observable` decorator to your function or method, then invoke it within the [Observability](../../reference/griptape/observability/observability.md) context manager. + +For example: + +```python title="PYTEST_IGNORE" +import time +from griptape.drivers import GriptapeCloudObservabilityDriver +from griptape.rules import Rule +from griptape.structures import Agent +from griptape.observability import Observability +from griptape.common import observable + +# Decorate a function +@observable +def my_function(): + time.sleep(3) + +class MyClass: + # Decorate a method + @observable + def my_method(self): + time.sleep(1) + my_function() + time.sleep(2) + +observability_driver = GriptapeCloudObservabilityDriver() + +# When invoking the instrumented code from within the Observability context manager, the +# telemetry for the custom code will be sent to the destination specified by the driver. +with Observability(observability_driver=observability_driver): + my_function() + MyClass().my_method() +``` \ No newline at end of file diff --git a/griptape/common/__init__.py b/griptape/common/__init__.py index 8324bcb9d..6ceff61eb 100644 --- a/griptape/common/__init__.py +++ b/griptape/common/__init__.py @@ -18,6 +18,7 @@ from .reference import Reference +from .observable import observable, Observable __all__ = [ "BaseMessage", @@ -35,4 +36,6 @@ "Reference", "BaseAction", "ToolAction", + "observable", + "Observable", ] diff --git a/griptape/common/observable.py b/griptape/common/observable.py new file mode 100644 index 000000000..aa675dfbe --- /dev/null +++ b/griptape/common/observable.py @@ -0,0 +1,77 @@ +from __future__ import annotations + +import functools +from inspect import isfunction +from typing import Any, Callable, Optional, TypeVar, cast + +from attrs import Factory, define, field + +T = TypeVar("T", bound=Callable) + + +def observable(*args: T | Any, **kwargs: Any) -> T: + return cast(T, Observable(*args, **kwargs)) + + +class Observable: + @define + class Call: + func: Callable = field(kw_only=True) + instance: Optional[Any] = field(default=None, kw_only=True) + args: tuple[Any, ...] = field(default=Factory(tuple), kw_only=True) + kwargs: dict[str, Any] = field(default=Factory(dict), kw_only=True) + decorator_args: tuple[Any, ...] = field(default=Factory(tuple), kw_only=True) + decorator_kwargs: dict[str, Any] = field(default=Factory(dict), kw_only=True) + + def __call__(self) -> Any: + # If self.func has a __self__ attribute, it is a bound method and we do not need to pass the instance. + args = (self.instance, *self.args) if self.instance and not hasattr(self.func, "__self__") else self.args + return self.func(*args, **self.kwargs) + + @property + def tags(self) -> Optional[list[str]]: + return self.decorator_kwargs.get("tags") + + def __init__(self, *args, **kwargs) -> None: + self._instance = None + if len(args) == 1 and len(kwargs) == 0 and isfunction(args[0]): + # Parameterless call. In otherwords, the `@observable` annotation + # was not followed by parentheses. + self._func = args[0] + functools.update_wrapper(self, self._func) + self.decorator_args = () + self.decorator_kwargs = {} + else: + # Parameterized call. In otherwords, the `@observable` annotation + # was followed by parentheses, for example `@observable()`, + # `@observable("x")` or `@observable(y="y")`. + self._func = None + self.decorator_args = args + self.decorator_kwargs = kwargs + + def __get__(self, obj: Any, objtype: Any = None) -> Observable: + self._instance = obj + return self + + def __call__(self, *args, **kwargs) -> Any: + if self._func: + # Parameterless call (self._func was a set in __init__) + from griptape.observability.observability import Observability + + return Observability.observe( + Observable.Call( + func=self._func, + instance=self._instance, + args=args, + kwargs=kwargs, + decorator_args=self.decorator_args, + decorator_kwargs=self.decorator_kwargs, + ) + ) + else: + # Parameterized call, create and return the "real" observable decorator + func = args[0] + decorated_func = Observable(func) + decorated_func.decorator_args = self.decorator_args + decorated_func.decorator_kwargs = self.decorator_kwargs + return decorated_func diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 4ecb6c9bd..8d84b68cf 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -109,6 +109,11 @@ from .audio_transcription.dummy_audio_transcription_driver import DummyAudioTranscriptionDriver from .audio_transcription.openai_audio_transcription_driver import OpenAiAudioTranscriptionDriver +from .observability.base_observability_driver import BaseObservabilityDriver +from .observability.no_op_observability_driver import NoOpObservabilityDriver +from .observability.open_telemetry_observability_driver import OpenTelemetryObservabilityDriver +from .observability.griptape_cloud_observability_driver import GriptapeCloudObservabilityDriver + __all__ = [ "BasePromptDriver", "OpenAiChatPromptDriver", @@ -202,4 +207,8 @@ "BaseAudioTranscriptionDriver", "DummyAudioTranscriptionDriver", "OpenAiAudioTranscriptionDriver", + "BaseObservabilityDriver", + "NoOpObservabilityDriver", + "OpenTelemetryObservabilityDriver", + "GriptapeCloudObservabilityDriver", ] diff --git a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py index cf9dd7bd2..733f0baa2 100644 --- a/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py +++ b/griptape/drivers/event_listener/griptape_cloud_event_listener_driver.py @@ -7,6 +7,7 @@ from attrs import Attribute, Factory, define, field from griptape.drivers.event_listener.base_event_listener_driver import BaseEventListenerDriver +from griptape.events.base_event import BaseEvent @define @@ -38,6 +39,17 @@ def validate_run_id(self, _: Attribute, structure_run_id: str) -> None: "structure_run_id must be set either in the constructor or as an environment variable (GT_CLOUD_STRUCTURE_RUN_ID).", ) + def publish_event(self, event: BaseEvent | dict, *, flush: bool = False) -> None: + from griptape.observability.observability import Observability + + event_payload = event.to_dict() if isinstance(event, BaseEvent) else event + + span_id = Observability.get_span_id() + if span_id is not None: + event_payload["span_id"] = span_id + + super().publish_event(event_payload, flush=flush) + def try_publish_event_payload(self, event_payload: dict) -> None: url = urljoin(self.base_url.strip("/"), f"/api/structure-runs/{self.structure_run_id}/events") diff --git a/griptape/drivers/observability/__init__.py b/griptape/drivers/observability/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/griptape/drivers/observability/base_observability_driver.py b/griptape/drivers/observability/base_observability_driver.py new file mode 100644 index 000000000..41b779578 --- /dev/null +++ b/griptape/drivers/observability/base_observability_driver.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from abc import ABC, abstractmethod +from typing import TYPE_CHECKING, Any, Optional + +from attrs import define + +if TYPE_CHECKING: + from types import TracebackType + + from griptape.common import Observable + + +@define +class BaseObservabilityDriver(ABC): + def __enter__(self) -> None: # noqa: B027 + pass + + def __exit__( + self, + exc_type: Optional[type[BaseException]], + exc_value: Optional[BaseException], + exc_traceback: Optional[TracebackType], + ) -> bool: + return False + + @abstractmethod + def observe(self, call: Observable.Call) -> Any: ... + + @abstractmethod + def get_span_id(self) -> Optional[str]: ... diff --git a/griptape/drivers/observability/griptape_cloud_observability_driver.py b/griptape/drivers/observability/griptape_cloud_observability_driver.py new file mode 100644 index 000000000..e520def50 --- /dev/null +++ b/griptape/drivers/observability/griptape_cloud_observability_driver.py @@ -0,0 +1,104 @@ +from __future__ import annotations + +import os +from typing import TYPE_CHECKING, Optional +from urllib.parse import urljoin +from uuid import UUID + +import requests +from attrs import Attribute, Factory, define, field +from opentelemetry.sdk.trace import TracerProvider +from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter, SpanExportResult +from opentelemetry.sdk.util import ns_to_iso_str +from opentelemetry.trace import INVALID_SPAN, get_current_span + +from griptape.drivers.observability.open_telemetry_observability_driver import OpenTelemetryObservabilityDriver + +if TYPE_CHECKING: + from collections.abc import Sequence + + from opentelemetry.sdk.trace import ReadableSpan, SpanProcessor + + +@define +class GriptapeCloudObservabilityDriver(OpenTelemetryObservabilityDriver): + @define + class SpanExporter(SpanExporter): + base_url: str = field(kw_only=True) + api_key: str = field(kw_only=True) + headers: dict = field(kw_only=True) + structure_run_id: str = field(kw_only=True) + + def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult: + url = urljoin(self.base_url.strip("/"), f"/api/structure-runs/{self.structure_run_id}/spans") + payload = [ + { + "trace_id": GriptapeCloudObservabilityDriver.format_trace_id(span.context.trace_id), + "span_id": GriptapeCloudObservabilityDriver.format_span_id(span.context.span_id), + "parent_id": GriptapeCloudObservabilityDriver.format_span_id(span.parent.span_id) + if span.parent + else None, + "name": span.name, + "start_time": ns_to_iso_str(span.start_time) if span.start_time else None, + "end_time": ns_to_iso_str(span.end_time) if span.end_time else None, + "status": span.status.status_code.name, + "attributes": {**span.attributes} if span.attributes else {}, + "events": [ + { + "name": event.name, + "timestamp": ns_to_iso_str(event.timestamp) if event.timestamp else None, + "attributes": {**event.attributes} if event.attributes else {}, + } + for event in span.events + ], + } + for span in spans + ] + response = requests.post(url=url, json=payload, headers=self.headers) + return SpanExportResult.SUCCESS if response.status_code == 200 else SpanExportResult.FAILURE + + service_name: str = field(default="griptape-cloud", kw_only=True) + base_url: str = field( + default=Factory(lambda: os.getenv("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")), kw_only=True + ) + api_key: str = field(default=Factory(lambda: os.getenv("GT_CLOUD_API_KEY")), kw_only=True) + headers: dict = field( + default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True + ) + structure_run_id: str = field(default=Factory(lambda: os.getenv("GT_CLOUD_STRUCTURE_RUN_ID")), kw_only=True) + span_processor: SpanProcessor = field( + default=Factory( + lambda self: BatchSpanProcessor( + GriptapeCloudObservabilityDriver.SpanExporter( + base_url=self.base_url, + api_key=self.api_key, + headers=self.headers, + structure_run_id=self.structure_run_id, + ) + ), + takes_self=True, + ), + kw_only=True, + ) + trace_provider: TracerProvider = field(default=Factory(lambda: TracerProvider()), kw_only=True) + + @structure_run_id.validator # pyright: ignore[reportAttributeAccessIssue] + def validate_run_id(self, _: Attribute, structure_run_id: str) -> None: + if structure_run_id is None: + raise ValueError( + "structure_run_id must be set either in the constructor or as an environment variable (GT_CLOUD_STRUCTURE_RUN_ID)." + ) + + @staticmethod + def format_trace_id(trace_id: int) -> str: + return str(UUID(int=trace_id)) + + @staticmethod + def format_span_id(span_id: int) -> str: + return str(UUID(int=span_id)) + + def get_span_id(self) -> Optional[str]: + span = get_current_span() + if span is INVALID_SPAN: + return None + return GriptapeCloudObservabilityDriver.format_span_id(span.get_span_context().span_id) diff --git a/griptape/drivers/observability/no_op_observability_driver.py b/griptape/drivers/observability/no_op_observability_driver.py new file mode 100644 index 000000000..c0fc9bfcf --- /dev/null +++ b/griptape/drivers/observability/no_op_observability_driver.py @@ -0,0 +1,19 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Optional + +from attrs import define + +from griptape.drivers import BaseObservabilityDriver + +if TYPE_CHECKING: + from griptape.common import Observable + + +@define +class NoOpObservabilityDriver(BaseObservabilityDriver): + def observe(self, call: Observable.Call) -> Any: + return call() + + def get_span_id(self) -> Optional[str]: + return None diff --git a/griptape/drivers/observability/open_telemetry_observability_driver.py b/griptape/drivers/observability/open_telemetry_observability_driver.py new file mode 100644 index 000000000..fec067a4b --- /dev/null +++ b/griptape/drivers/observability/open_telemetry_observability_driver.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Optional + +from attrs import Factory, define, field +from opentelemetry.instrumentation.threading import ThreadingInstrumentor +from opentelemetry.sdk.resources import Resource +from opentelemetry.sdk.trace import SpanProcessor, TracerProvider +from opentelemetry.trace import INVALID_SPAN, Status, StatusCode, Tracer, format_span_id, get_current_span, get_tracer + +from griptape.drivers import BaseObservabilityDriver + +if TYPE_CHECKING: + from types import TracebackType + + from griptape.common import Observable + + +@define +class OpenTelemetryObservabilityDriver(BaseObservabilityDriver): + service_name: str = field(kw_only=True) + span_processor: SpanProcessor = field(kw_only=True) + trace_provider: TracerProvider = field( + default=Factory( + lambda self: TracerProvider(resource=Resource(attributes={"service.name": self.service_name})), + takes_self=True, + ), + kw_only=True, + ) + _tracer: Optional[Tracer] = None + _root_span_context_manager: Any = None + + def __attrs_post_init__(self) -> None: + self.trace_provider.add_span_processor(self.span_processor) + self._tracer = get_tracer(self.service_name, tracer_provider=self.trace_provider) + + def __enter__(self) -> None: + ThreadingInstrumentor().instrument() + self._root_span_context_manager = self._tracer.start_as_current_span("main") # pyright: ignore[reportCallIssue] + self._root_span_context_manager.__enter__() + + def __exit__( + self, + exc_type: Optional[type[BaseException]], + exc_value: Optional[BaseException], + exc_traceback: Optional[TracebackType], + ) -> bool: + root_span = get_current_span() + if exc_value: + root_span = get_current_span() + root_span.set_status(Status(StatusCode.ERROR)) + root_span.record_exception(exc_value) + else: + root_span.set_status(Status(StatusCode.OK)) + if self._root_span_context_manager: + self._root_span_context_manager.__exit__(exc_type, exc_value, exc_traceback) + self._root_span_context_manager = None + self.trace_provider.force_flush() + ThreadingInstrumentor().uninstrument() + return False + + def observe(self, call: Observable.Call) -> Any: + func = call.func + instance = call.instance + tags = call.tags + + class_name = f"{instance.__class__.__name__}." if instance else "" + span_name = f"{class_name}{func.__name__}()" + with self._tracer.start_as_current_span(span_name) as span: # pyright: ignore[reportCallIssue] + if tags is not None: + span.set_attribute("tags", tags) + + try: + result = call() + span.set_status(Status(StatusCode.OK)) + return result + except Exception as e: + span.set_status(Status(StatusCode.ERROR)) + span.record_exception(e) + raise e + + def get_span_id(self) -> Optional[str]: + span = get_current_span() + if span is INVALID_SPAN: + return None + return format_span_id(span.get_span_context().span_id) diff --git a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py index 4cb5801d3..b663d06fd 100644 --- a/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_bedrock_prompt_driver.py @@ -26,6 +26,7 @@ TextDeltaMessageContent, TextMessageContent, ToolAction, + observable, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AmazonBedrockTokenizer, BaseTokenizer @@ -55,6 +56,7 @@ class AmazonBedrockPromptDriver(BasePromptDriver): use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) tool_choice: dict = field(default=Factory(lambda: {"auto": {}}), kw_only=True, metadata={"serializable": True}) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: response = self.bedrock_client.converse(**self._base_params(prompt_stack)) @@ -67,6 +69,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: usage=Message.Usage(input_tokens=usage["inputTokens"], output_tokens=usage["outputTokens"]), ) + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: response = self.bedrock_client.converse_stream(**self._base_params(prompt_stack)) diff --git a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py index 09eadace5..c31e66abc 100644 --- a/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py +++ b/griptape/drivers/prompt/amazon_sagemaker_jumpstart_prompt_driver.py @@ -6,7 +6,7 @@ from attrs import Attribute, Factory, define, field from griptape.artifacts import TextArtifact -from griptape.common import DeltaMessage, Message, PromptStack, TextMessageContent +from griptape.common import DeltaMessage, Message, PromptStack, TextMessageContent, observable from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import import_optional_dependency @@ -44,6 +44,7 @@ def validate_stream(self, _: Attribute, stream: bool) -> None: # noqa: FBT001 if stream: raise ValueError("streaming is not supported") + @observable def try_run(self, prompt_stack: PromptStack) -> Message: payload = { "inputs": self.prompt_stack_to_string(prompt_stack), @@ -81,6 +82,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), ) + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: raise NotImplementedError("streaming is not supported") diff --git a/griptape/drivers/prompt/anthropic_prompt_driver.py b/griptape/drivers/prompt/anthropic_prompt_driver.py index 14be9a26b..ae50bc59e 100644 --- a/griptape/drivers/prompt/anthropic_prompt_driver.py +++ b/griptape/drivers/prompt/anthropic_prompt_driver.py @@ -27,6 +27,7 @@ TextDeltaMessageContent, TextMessageContent, ToolAction, + observable, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import AnthropicTokenizer, BaseTokenizer @@ -70,6 +71,7 @@ class AnthropicPromptDriver(BasePromptDriver): use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) max_tokens: int = field(default=1000, kw_only=True, metadata={"serializable": True}) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: response = self.client.messages.create(**self._base_params(prompt_stack)) @@ -79,6 +81,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: usage=Message.Usage(input_tokens=response.usage.input_tokens, output_tokens=response.usage.output_tokens), ) + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: events = self.client.messages.create(**self._base_params(prompt_stack), stream=True) diff --git a/griptape/drivers/prompt/base_prompt_driver.py b/griptape/drivers/prompt/base_prompt_driver.py index f2a5522d6..0a67b4f4e 100644 --- a/griptape/drivers/prompt/base_prompt_driver.py +++ b/griptape/drivers/prompt/base_prompt_driver.py @@ -14,6 +14,7 @@ PromptStack, TextDeltaMessageContent, TextMessageContent, + observable, ) from griptape.events import CompletionChunkEvent, FinishPromptEvent, StartPromptEvent from griptape.mixins import ExponentialBackoffMixin, SerializableMixin @@ -65,6 +66,7 @@ def after_run(self, result: Message) -> None: ), ) + @observable(tags=["PromptDriver.run()"]) def run(self, prompt_stack: PromptStack) -> Message: for attempt in self.retrying(): with attempt: diff --git a/griptape/drivers/prompt/cohere_prompt_driver.py b/griptape/drivers/prompt/cohere_prompt_driver.py index 0a28a9c59..ff1a8b482 100644 --- a/griptape/drivers/prompt/cohere_prompt_driver.py +++ b/griptape/drivers/prompt/cohere_prompt_driver.py @@ -17,6 +17,7 @@ TextDeltaMessageContent, TextMessageContent, ToolAction, + observable, ) from griptape.common.prompt_stack.contents.action_call_delta_message_content import ActionCallDeltaMessageContent from griptape.drivers import BasePromptDriver @@ -53,6 +54,7 @@ class CoherePromptDriver(BasePromptDriver): force_single_step: bool = field(default=False, kw_only=True, metadata={"serializable": True}) use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: result = self.client.chat(**self._base_params(prompt_stack)) usage = result.meta.tokens @@ -63,6 +65,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: usage=Message.Usage(input_tokens=usage.input_tokens, output_tokens=usage.output_tokens), ) + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: result = self.client.chat_stream(**self._base_params(prompt_stack)) diff --git a/griptape/drivers/prompt/dummy_prompt_driver.py b/griptape/drivers/prompt/dummy_prompt_driver.py index c26d53794..9ed1f45ec 100644 --- a/griptape/drivers/prompt/dummy_prompt_driver.py +++ b/griptape/drivers/prompt/dummy_prompt_driver.py @@ -4,6 +4,7 @@ from attrs import Factory, define, field +from griptape.common import observable from griptape.drivers import BasePromptDriver from griptape.exceptions import DummyException from griptape.tokenizers import DummyTokenizer @@ -19,8 +20,10 @@ class DummyPromptDriver(BasePromptDriver): model: None = field(init=False, default=None, kw_only=True) tokenizer: DummyTokenizer = field(default=Factory(lambda: DummyTokenizer()), kw_only=True) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: raise DummyException(__class__.__name__, "try_run") + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: raise DummyException(__class__.__name__, "try_stream") diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index c85835826..3a32ebca7 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -20,6 +20,7 @@ TextDeltaMessageContent, TextMessageContent, ToolAction, + observable, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer, GoogleTokenizer @@ -62,6 +63,7 @@ class GooglePromptDriver(BasePromptDriver): use_native_tools: bool = field(default=True, kw_only=True, metadata={"serializable": True}) tool_choice: str = field(default="auto", kw_only=True, metadata={"serializable": True}) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: messages = self.__to_google_messages(prompt_stack) response: GenerateContentResponse = self.model_client.generate_content( @@ -80,6 +82,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: ), ) + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: messages = self.__to_google_messages(prompt_stack) response: GenerateContentResponse = self.model_client.generate_content( diff --git a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py index 072b01ab5..71244ddf0 100644 --- a/griptape/drivers/prompt/huggingface_hub_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_hub_prompt_driver.py @@ -4,7 +4,7 @@ from attrs import Factory, define, field -from griptape.common import DeltaMessage, Message, PromptStack, TextDeltaMessageContent +from griptape.common import DeltaMessage, Message, PromptStack, TextDeltaMessageContent, observable from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import import_optional_dependency @@ -50,6 +50,7 @@ class HuggingFaceHubPromptDriver(BasePromptDriver): kw_only=True, ) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: prompt = self.prompt_stack_to_string(prompt_stack) @@ -68,6 +69,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: usage=Message.Usage(input_tokens=input_tokens, output_tokens=output_tokens), ) + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: prompt = self.prompt_stack_to_string(prompt_stack) diff --git a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py index 992aff918..fb475bdd7 100644 --- a/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py +++ b/griptape/drivers/prompt/huggingface_pipeline_prompt_driver.py @@ -5,7 +5,7 @@ from attrs import Factory, define, field from griptape.artifacts import TextArtifact -from griptape.common import DeltaMessage, Message, PromptStack, TextMessageContent +from griptape.common import DeltaMessage, Message, PromptStack, TextMessageContent, observable from griptape.drivers import BasePromptDriver from griptape.tokenizers import HuggingFaceTokenizer from griptape.utils import import_optional_dependency @@ -47,6 +47,7 @@ class HuggingFacePipelinePromptDriver(BasePromptDriver): ), ) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: messages = self._prompt_stack_to_messages(prompt_stack) @@ -75,6 +76,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: else: raise Exception("invalid output format") + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: raise NotImplementedError("streaming is not supported") diff --git a/griptape/drivers/prompt/ollama_prompt_driver.py b/griptape/drivers/prompt/ollama_prompt_driver.py index fb1e28e87..ea4f8b344 100644 --- a/griptape/drivers/prompt/ollama_prompt_driver.py +++ b/griptape/drivers/prompt/ollama_prompt_driver.py @@ -13,6 +13,7 @@ PromptStack, TextDeltaMessageContent, TextMessageContent, + observable, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import SimpleTokenizer @@ -61,6 +62,7 @@ class OllamaPromptDriver(BasePromptDriver): kw_only=True, ) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: response = self.client.chat(**self._base_params(prompt_stack)) @@ -72,6 +74,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: else: raise Exception("invalid model response") + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: stream = self.client.chat(**self._base_params(prompt_stack), stream=True) diff --git a/griptape/drivers/prompt/openai_chat_prompt_driver.py b/griptape/drivers/prompt/openai_chat_prompt_driver.py index 9c4ab9a74..c845aa6c5 100644 --- a/griptape/drivers/prompt/openai_chat_prompt_driver.py +++ b/griptape/drivers/prompt/openai_chat_prompt_driver.py @@ -21,6 +21,7 @@ TextDeltaMessageContent, TextMessageContent, ToolAction, + observable, ) from griptape.drivers import BasePromptDriver from griptape.tokenizers import BaseTokenizer, OpenAiTokenizer @@ -88,6 +89,7 @@ class OpenAiChatPromptDriver(BasePromptDriver): kw_only=True, ) + @observable def try_run(self, prompt_stack: PromptStack) -> Message: result = self.client.chat.completions.create(**self._base_params(prompt_stack)) @@ -105,6 +107,7 @@ def try_run(self, prompt_stack: PromptStack) -> Message: else: raise Exception("Completion with more than one choice is not supported yet.") + @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: result = self.client.chat.completions.create(**self._base_params(prompt_stack), stream=True) diff --git a/griptape/observability/__init__.py b/griptape/observability/__init__.py new file mode 100644 index 000000000..a17bb63f6 --- /dev/null +++ b/griptape/observability/__init__.py @@ -0,0 +1,3 @@ +from .observability import Observability + +__all__ = ["Observability"] diff --git a/griptape/observability/observability.py b/griptape/observability/observability.py new file mode 100644 index 000000000..1cbc589eb --- /dev/null +++ b/griptape/observability/observability.py @@ -0,0 +1,57 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any, Optional + +from attrs import define, field + +from griptape.common import Observable +from griptape.drivers import BaseObservabilityDriver, NoOpObservabilityDriver + +_no_op_observability_driver = NoOpObservabilityDriver() +_global_observability_driver: Optional[BaseObservabilityDriver] = None + +if TYPE_CHECKING: + from types import TracebackType + + from griptape.common import Observable + + +@define +class Observability: + observability_driver: BaseObservabilityDriver = field(kw_only=True) + + @staticmethod + def get_global_driver() -> Optional[BaseObservabilityDriver]: + global _global_observability_driver + return _global_observability_driver + + @staticmethod + def set_global_driver(driver: Optional[BaseObservabilityDriver]) -> None: + global _global_observability_driver + _global_observability_driver = driver + + @staticmethod + def observe(call: Observable.Call) -> Any: + driver = Observability.get_global_driver() or _no_op_observability_driver + return driver.observe(call) + + @staticmethod + def get_span_id() -> Optional[str]: + driver = Observability.get_global_driver() or _no_op_observability_driver + return driver.get_span_id() + + def __enter__(self) -> None: + if Observability.get_global_driver() is not None: + raise ValueError("Observability driver already set.") + Observability.set_global_driver(self.observability_driver) + self.observability_driver.__enter__() + + def __exit__( + self, + exc_type: Optional[type[BaseException]], + exc_value: Optional[BaseException], + exc_traceback: Optional[TracebackType], + ) -> bool: + Observability.set_global_driver(None) + self.observability_driver.__exit__(exc_type, exc_value, exc_traceback) + return False diff --git a/griptape/structures/agent.py b/griptape/structures/agent.py index 693a98c34..b133a7b6b 100644 --- a/griptape/structures/agent.py +++ b/griptape/structures/agent.py @@ -5,6 +5,7 @@ from attrs import Attribute, define, field from griptape.artifacts.text_artifact import TextArtifact +from griptape.common import observable from griptape.memory.structure import Run from griptape.structures import Structure from griptape.tasks import PromptTask, ToolkitTask @@ -57,6 +58,7 @@ def add_tasks(self, *tasks: BaseTask) -> list[BaseTask]: raise ValueError("Agents can only have one task.") return super().add_tasks(*tasks) + @observable def try_run(self, *args) -> Agent: self.task.execute() diff --git a/griptape/structures/pipeline.py b/griptape/structures/pipeline.py index b768cf6c6..0aed369bb 100644 --- a/griptape/structures/pipeline.py +++ b/griptape/structures/pipeline.py @@ -5,6 +5,7 @@ from attrs import define from griptape.artifacts import ErrorArtifact +from griptape.common import observable from griptape.memory.structure import Run from griptape.structures import Structure @@ -45,6 +46,7 @@ def insert_task(self, parent_task: BaseTask, task: BaseTask) -> BaseTask: return task + @observable def try_run(self, *args) -> Pipeline: self.__run_from_task(self.input_task) diff --git a/griptape/structures/structure.py b/griptape/structures/structure.py index 13c247824..0a296f980 100644 --- a/griptape/structures/structure.py +++ b/griptape/structures/structure.py @@ -10,6 +10,7 @@ from rich.logging import RichHandler from griptape.artifacts import BaseArtifact, BlobArtifact, TextArtifact +from griptape.common import observable from griptape.config import BaseStructureConfig, OpenAiStructureConfig, StructureConfig from griptape.drivers import BaseEmbeddingDriver, BasePromptDriver, OpenAiChatPromptDriver, OpenAiEmbeddingDriver from griptape.drivers.vector.local_vector_store_driver import LocalVectorStoreDriver @@ -255,6 +256,7 @@ def resolve_relationships(self) -> None: if task.id not in child.parent_ids: child.parent_ids.append(task.id) + @observable def before_run(self, args: Any) -> None: self._execution_args = args @@ -270,6 +272,7 @@ def before_run(self, args: Any) -> None: self.resolve_relationships() + @observable def after_run(self) -> None: self.publish_event( FinishStructureRunEvent( @@ -283,6 +286,7 @@ def after_run(self) -> None: @abstractmethod def add_task(self, task: BaseTask) -> BaseTask: ... + @observable def run(self, *args) -> Structure: self.before_run(args) diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index 32485af7b..2ecfb8676 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -7,6 +7,7 @@ from graphlib import TopologicalSorter from griptape.artifacts import ErrorArtifact +from griptape.common import observable from griptape.memory.structure import Run from griptape.structures import Structure @@ -82,6 +83,7 @@ def insert_task( return task + @observable def try_run(self, *args) -> Workflow: exit_loop = False diff --git a/griptape/tools/base_tool.py b/griptape/tools/base_tool.py index 91b90e775..3fb6af26b 100644 --- a/griptape/tools/base_tool.py +++ b/griptape/tools/base_tool.py @@ -14,6 +14,7 @@ from schema import Literal, Or, Schema from griptape.artifacts import BaseArtifact, ErrorArtifact, InfoArtifact, TextArtifact +from griptape.common import observable from griptape.mixins import ActivityMixin if TYPE_CHECKING: @@ -122,6 +123,7 @@ def execute(self, activity: Callable, subtask: ActionsSubtask, action: ToolActio def before_run(self, activity: Callable, subtask: ActionsSubtask, action: ToolAction) -> Optional[dict]: return action.input + @observable(tags=["Tool.run()"]) def run( self, activity: Callable, diff --git a/poetry.lock b/poetry.lock index d654c99f5..3ae72743c 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1188,6 +1188,23 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "deprecated" +version = "1.2.14" +description = "Python @deprecated decorator to deprecate old python classes, functions or methods." +optional = true +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"}, + {file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"}, +] + +[package.dependencies] +wrapt = ">=1.10,<2" + +[package.extras] +dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"] + [[package]] name = "distlib" version = "0.3.8" @@ -3572,6 +3589,131 @@ develop = ["black", "botocore", "coverage (<8.0.0)", "jinja2", "mock", "myst-par docs = ["aiohttp (>=3,<4)", "myst-parser", "sphinx", "sphinx-copybutton", "sphinx-rtd-theme"] kerberos = ["requests-kerberos"] +[[package]] +name = "opentelemetry-api" +version = "1.25.0" +description = "OpenTelemetry Python API" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_api-1.25.0-py3-none-any.whl", hash = "sha256:757fa1aa020a0f8fa139f8959e53dec2051cc26b832e76fa839a6d76ecefd737"}, + {file = "opentelemetry_api-1.25.0.tar.gz", hash = "sha256:77c4985f62f2614e42ce77ee4c9da5fa5f0bc1e1821085e9a47533a9323ae869"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +importlib-metadata = ">=6.0,<=7.1" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-common" +version = "1.25.0" +description = "OpenTelemetry Protobuf encoding" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_exporter_otlp_proto_common-1.25.0-py3-none-any.whl", hash = "sha256:15637b7d580c2675f70246563363775b4e6de947871e01d0f4e3881d1848d693"}, + {file = "opentelemetry_exporter_otlp_proto_common-1.25.0.tar.gz", hash = "sha256:c93f4e30da4eee02bacd1e004eb82ce4da143a2f8e15b987a9f603e0a85407d3"}, +] + +[package.dependencies] +opentelemetry-proto = "1.25.0" + +[[package]] +name = "opentelemetry-exporter-otlp-proto-http" +version = "1.25.0" +description = "OpenTelemetry Collector Protobuf over HTTP Exporter" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_exporter_otlp_proto_http-1.25.0-py3-none-any.whl", hash = "sha256:2eca686ee11b27acd28198b3ea5e5863a53d1266b91cda47c839d95d5e0541a6"}, + {file = "opentelemetry_exporter_otlp_proto_http-1.25.0.tar.gz", hash = "sha256:9f8723859e37c75183ea7afa73a3542f01d0fd274a5b97487ea24cb683d7d684"}, +] + +[package.dependencies] +deprecated = ">=1.2.6" +googleapis-common-protos = ">=1.52,<2.0" +opentelemetry-api = ">=1.15,<2.0" +opentelemetry-exporter-otlp-proto-common = "1.25.0" +opentelemetry-proto = "1.25.0" +opentelemetry-sdk = ">=1.25.0,<1.26.0" +requests = ">=2.7,<3.0" + +[[package]] +name = "opentelemetry-instrumentation" +version = "0.46b0" +description = "Instrumentation Tools & Auto Instrumentation for OpenTelemetry Python" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_instrumentation-0.46b0-py3-none-any.whl", hash = "sha256:89cd721b9c18c014ca848ccd11181e6b3fd3f6c7669e35d59c48dc527408c18b"}, + {file = "opentelemetry_instrumentation-0.46b0.tar.gz", hash = "sha256:974e0888fb2a1e01c38fbacc9483d024bb1132aad92d6d24e2e5543887a7adda"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.4,<2.0" +setuptools = ">=16.0" +wrapt = ">=1.0.0,<2.0.0" + +[[package]] +name = "opentelemetry-instrumentation-threading" +version = "0.46b0" +description = "Thread context propagation support for OpenTelemetry" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_instrumentation_threading-0.46b0-py3-none-any.whl", hash = "sha256:60fe4e86a8e399c187eeafccfeeefa07d5b9d4382bc9c4f52ab5436d6bb244bf"}, + {file = "opentelemetry_instrumentation_threading-0.46b0.tar.gz", hash = "sha256:938dacb52b2ac1114678d146d2ef2d0044f3e32ec8b2045db36d709de6c95548"}, +] + +[package.dependencies] +opentelemetry-api = ">=1.12,<2.0" +opentelemetry-instrumentation = "0.46b0" +wrapt = ">=1.0.0,<2.0.0" + +[[package]] +name = "opentelemetry-proto" +version = "1.25.0" +description = "OpenTelemetry Python Proto" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_proto-1.25.0-py3-none-any.whl", hash = "sha256:f07e3341c78d835d9b86665903b199893befa5e98866f63d22b00d0b7ca4972f"}, + {file = "opentelemetry_proto-1.25.0.tar.gz", hash = "sha256:35b6ef9dc4a9f7853ecc5006738ad40443701e52c26099e197895cbda8b815a3"}, +] + +[package.dependencies] +protobuf = ">=3.19,<5.0" + +[[package]] +name = "opentelemetry-sdk" +version = "1.25.0" +description = "OpenTelemetry Python SDK" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_sdk-1.25.0-py3-none-any.whl", hash = "sha256:d97ff7ec4b351692e9d5a15af570c693b8715ad78b8aafbec5c7100fe966b4c9"}, + {file = "opentelemetry_sdk-1.25.0.tar.gz", hash = "sha256:ce7fc319c57707ef5bf8b74fb9f8ebdb8bfafbe11898410e0d2a761d08a98ec7"}, +] + +[package.dependencies] +opentelemetry-api = "1.25.0" +opentelemetry-semantic-conventions = "0.46b0" +typing-extensions = ">=3.7.4" + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.46b0" +description = "OpenTelemetry Semantic Conventions" +optional = true +python-versions = ">=3.8" +files = [ + {file = "opentelemetry_semantic_conventions-0.46b0-py3-none-any.whl", hash = "sha256:6daef4ef9fa51d51855d9f8e0ccd3a1bd59e0e545abe99ac6203804e36ab3e07"}, + {file = "opentelemetry_semantic_conventions-0.46b0.tar.gz", hash = "sha256:fbc982ecbb6a6e90869b15c1673be90bd18c8a56ff1cffc0864e38e2edffaefa"}, +] + +[package.dependencies] +opentelemetry-api = "1.25.0" + [[package]] name = "packaging" version = "24.0" @@ -4726,6 +4868,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -6399,6 +6542,85 @@ MarkupSafe = ">=2.1.1" [package.extras] watchdog = ["watchdog (>=2.3)"] +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = true +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + [[package]] name = "xmltodict" version = "0.13.0" @@ -6529,7 +6751,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] @@ -6542,6 +6764,8 @@ drivers-event-listener-amazon-sqs = ["boto3"] drivers-event-listener-pusher = ["pusher"] drivers-memory-conversation-amazon-dynamodb = ["boto3"] drivers-memory-conversation-redis = ["redis"] +drivers-observability-griptape-cloud = ["opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk"] +drivers-observability-opentelemetry = ["opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk"] drivers-prompt-amazon-bedrock = ["anthropic", "boto3"] drivers-prompt-amazon-sagemaker = ["boto3", "transformers"] drivers-prompt-anthropic = ["anthropic"] @@ -6574,4 +6798,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a49e3177bd216b5af2ffe2f213d1e2d8081f23ef33e4c71ecc16c673287823fa" +content-hash = "9bd25bfc6e645b80acebb1266659832642799443b5f7314dc42487f4e67f1e42" diff --git a/pyproject.toml b/pyproject.toml index fabce497e..510209d82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,6 +55,11 @@ qdrant-client = { version = ">=1.9.1", optional = true } pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} duckduckgo-search = {version = "^6.1.12", optional = true} +opentelemetry-sdk = {version = "^1.25.0", optional = true} +opentelemetry-api = {version = "^1.25.0", optional = true} +opentelemetry-instrumentation = {version = "^0.46b0", optional = true} +opentelemetry-instrumentation-threading = {version = "^0.46b0", optional = true} +opentelemetry-exporter-otlp-proto-http = {version = "^1.25.0", optional = true} # loaders pandas = {version = "^1.3", optional = true} @@ -108,6 +113,21 @@ drivers-event-listener-pusher = ["pusher"] drivers-rerank-cohere = ["cohere"] +drivers-observability-opentelemetry = [ + "opentelemetry-sdk", + "opentelemetry-api", + "opentelemetry-instrumentation", + "opentelemetry-instrumentation-threading", + "opentelemetry-exporter-otlp-proto-http", +] +drivers-observability-griptape-cloud = [ + "opentelemetry-sdk", + "opentelemetry-api", + "opentelemetry-instrumentation", + "opentelemetry-instrumentation-threading", + "opentelemetry-exporter-otlp-proto-http", +] + loaders-dataframe = ["pandas"] loaders-pdf = ["pypdf"] loaders-image = ["pillow"] @@ -142,6 +162,11 @@ all = [ "pusher", "ollama", "duckduckgo-search", + "opentelemetry-sdk", + "opentelemetry-api", + "opentelemetry-instrumentation", + "opentelemetry-instrumentation-threading", + "opentelemetry-exporter-otlp-proto-http", # loaders "pandas", diff --git a/tests/unit/common/test_observable.py b/tests/unit/common/test_observable.py new file mode 100644 index 000000000..f48c3086c --- /dev/null +++ b/tests/unit/common/test_observable.py @@ -0,0 +1,238 @@ +from unittest.mock import call + +import pytest + +import griptape.observability.observability as observability +from griptape.common.observable import Observable + + +class TestObservable: + @pytest.fixture() + def observe_spy(self, mocker): + return mocker.spy(observability.Observability, "observe") + + def test_observable_function_no_parenthesis(self, observe_spy): + from griptape.common import observable + + @observable + def bar(*args, **kwargs): + """Bar's docstring.""" + if args: + return args[0] + + assert bar() is None + assert bar("a") == "a" + assert bar("b", "2") == "b" + assert bar("c", x="y") == "c" + + original_bar = bar.__wrapped__ + assert bar.__name__ == original_bar.__name__ + assert bar.__name__ == "bar" + assert bar.__doc__ == original_bar.__doc__ + assert bar.__doc__ == "Bar's docstring." + + assert observe_spy.call_count == 4 + observe_spy.assert_has_calls( + [ + call(Observable.Call(func=original_bar, args=())), + call(Observable.Call(func=original_bar, args=("a",))), + call(Observable.Call(func=original_bar, args=("b", "2"))), + call(Observable.Call(func=original_bar, args=("c",), kwargs={"x": "y"})), + ] + ) + + def test_observable_function_empty_parenthesis(self, observe_spy): + from griptape.common import observable + + @observable() + def bar(*args, **kwargs): + if args: + return args[0] + + assert bar() is None + assert bar("a") == "a" + assert bar("b", "2") == "b" + assert bar("c", x="y") == "c" + + original_bar = bar.__wrapped__ + + assert observe_spy.call_count == 4 + observe_spy.assert_has_calls( + [ + call(Observable.Call(func=original_bar, args=())), + call(Observable.Call(func=original_bar, args=("a",))), + call(Observable.Call(func=original_bar, args=("b", "2"))), + call(Observable.Call(func=original_bar, args=("c",), kwargs={"x": "y"})), + ] + ) + + def test_observable_function_args(self, observe_spy): + from griptape.common import observable + + @observable("one", 2, {"th": "ree"}, a="b", b=6) + def bar(*args, **kwargs): + if args: + return args[0] + + assert bar() is None + assert bar("a") == "a" + assert bar("b", "2") == "b" + assert bar("c", x="y") == "c" + + original_bar = bar.__wrapped__ + + assert observe_spy.call_count == 4 + observe_spy.assert_has_calls( + [ + call( + Observable.Call( + func=original_bar, + args=(), + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + call( + Observable.Call( + func=original_bar, + args=("a",), + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + call( + Observable.Call( + func=original_bar, + args=("b", "2"), + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + call( + Observable.Call( + func=original_bar, + args=("c",), + kwargs={"x": "y"}, + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + ] + ) + + def test_observable_method_no_parenthesis(self, observe_spy): + from griptape.common import observable + + class Foo: + @observable + def bar(self, *args, **kwargs): + if args: + return args[0] + return None + + foo = Foo() + assert foo.bar() is None + assert foo.bar("a") == "a" + assert foo.bar("b", "2") == "b" + assert foo.bar("c", x="y") == "c" + + original_bar = foo.bar.__wrapped__ + + assert observe_spy.call_count == 4 + observe_spy.assert_has_calls( + [ + call(Observable.Call(func=original_bar, instance=foo, args=())), + call(Observable.Call(func=original_bar, instance=foo, args=("a",))), + call(Observable.Call(func=original_bar, instance=foo, args=("b", "2"))), + call(Observable.Call(func=original_bar, instance=foo, args=("c",), kwargs={"x": "y"})), + ] + ) + + def test_observable_method_empty_parenthesis(self, observe_spy): + from griptape.common import observable + + class Foo: + @observable() + def bar(self, *args, **kwargs): + if args: + return args[0] + return None + + foo = Foo() + assert foo.bar() is None + assert foo.bar("a") == "a" + assert foo.bar("b", "2") == "b" + assert foo.bar("c", x="y") == "c" + + original_bar = foo.bar.__wrapped__ + + assert observe_spy.call_count == 4 + observe_spy.assert_has_calls( + [ + call(Observable.Call(func=original_bar, instance=foo, args=())), + call(Observable.Call(func=original_bar, instance=foo, args=("a",))), + call(Observable.Call(func=original_bar, instance=foo, args=("b", "2"))), + call(Observable.Call(func=original_bar, instance=foo, args=("c",), kwargs={"x": "y"})), + ] + ) + + def test_observable_method_args(self, observe_spy): + from griptape.common import observable + + class Foo: + @observable("one", 2, {"th": "ree"}, a="b", b=6) + def bar(self, *args, **kwargs): + if args: + return args[0] + return None + + foo = Foo() + assert foo.bar() is None + assert foo.bar("a") == "a" + assert foo.bar("b", "2") == "b" + assert foo.bar("c", x="y") == "c" + + original_bar = foo.bar.__wrapped__ + + assert observe_spy.call_count == 4 + observe_spy.assert_has_calls( + [ + call( + Observable.Call( + func=original_bar, + instance=foo, + args=(), + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + call( + Observable.Call( + func=original_bar, + instance=foo, + args=("a",), + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + call( + Observable.Call( + func=original_bar, + instance=foo, + args=("b", "2"), + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + call( + Observable.Call( + func=original_bar, + instance=foo, + args=("c",), + kwargs={"x": "y"}, + decorator_args=("one", 2, {"th": "ree"}), + decorator_kwargs={"a": "b", "b": 6}, + ) + ), + ] + ) diff --git a/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py b/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py index 5db78b76f..1cd198756 100644 --- a/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_griptape_cloud_event_listener_driver.py @@ -1,9 +1,10 @@ import os -from unittest.mock import Mock +from unittest.mock import MagicMock, Mock import pytest from griptape.drivers.event_listener.griptape_cloud_event_listener_driver import GriptapeCloudEventListenerDriver +from griptape.observability.observability import Observability from tests.mocks.mock_event import MockEvent @@ -42,6 +43,30 @@ def test_init(self, driver): assert driver.api_key == "foo bar" assert driver.structure_run_id == "bar baz" + def test_publish_event_without_span_id(self, mock_post, driver): + event = MockEvent() + driver.publish_event(event, flush=True) + + mock_post.assert_called_with( + url="https://cloud123.griptape.ai/api/structure-runs/bar baz/events", + json=[event.to_dict()], + headers={"Authorization": "Bearer foo bar"}, + ) + + def test_publish_event_with_span_id(self, mock_post, driver): + event = MockEvent() + observability_driver = MagicMock() + observability_driver.get_span_id.return_value = "test" + + with Observability(observability_driver=observability_driver): + driver.publish_event(event, flush=True) + + mock_post.assert_called_with( + url="https://cloud123.griptape.ai/api/structure-runs/bar baz/events", + json=[{**event.to_dict(), "span_id": "test"}], + headers={"Authorization": "Bearer foo bar"}, + ) + def test_try_publish_event_payload(self, mock_post, driver): event = MockEvent() driver.try_publish_event_payload(event.to_dict()) diff --git a/tests/unit/drivers/observability/__init__.py b/tests/unit/drivers/observability/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/drivers/observability/test_griptape_cloud_observability_driver.py b/tests/unit/drivers/observability/test_griptape_cloud_observability_driver.py new file mode 100644 index 000000000..f559a9077 --- /dev/null +++ b/tests/unit/drivers/observability/test_griptape_cloud_observability_driver.py @@ -0,0 +1,284 @@ +import os +from uuid import UUID + +import pytest +from opentelemetry.sdk.trace import Event, ReadableSpan +from opentelemetry.trace import SpanContext, Status, StatusCode + +from griptape.common import Observable +from griptape.drivers import GriptapeCloudObservabilityDriver +from tests.utils.expected_spans import ExpectedSpan, ExpectedSpans + + +class TestGriptapeCloudObservabilityDriver: + @pytest.fixture() + def driver(self): + environ = { + "GT_CLOUD_BASE_URL": "http://base-url:1234", + "GT_CLOUD_API_KEY": "api-key", + "GT_CLOUD_STRUCTURE_RUN_ID": "structure-run-id", + } + original_environ = {} + for key in environ: + original_environ[key] = environ.get(key) + os.environ[key] = environ[key] + + yield GriptapeCloudObservabilityDriver() + + for key, value in original_environ.items(): + if value is None: + del os.environ[key] + else: + os.environ[key] = value + + @pytest.fixture(autouse=True) + def mock_span_exporter_class(self, mocker): + return mocker.patch( + "griptape.drivers.observability.griptape_cloud_observability_driver.GriptapeCloudObservabilityDriver.SpanExporter" + ) + + @pytest.fixture() + def mock_span_exporter(self, mock_span_exporter_class): + return mock_span_exporter_class.return_value + + def test_init(self, mock_span_exporter_class, mock_span_exporter): + GriptapeCloudObservabilityDriver( + base_url="http://base-url:1234", api_key="api-key", structure_run_id="structure-run-id" + ) + + assert mock_span_exporter_class.call_count == 1 + mock_span_exporter_class.assert_called_once_with( + base_url="http://base-url:1234", + api_key="api-key", + headers={"Authorization": "Bearer api-key"}, + structure_run_id="structure-run-id", + ) + + mock_span_exporter.export.assert_not_called() + + def test_init_raises_when_structure_run_is_none(self): + with pytest.raises(ValueError, match="structure_run_id must be set"): + GriptapeCloudObservabilityDriver(structure_run_id=None) + + def test_context_manager_pass(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans(spans=[ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK)]) + + with driver: + pass + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + # Works second time too + with driver: + pass + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_context_manager_pass_exc(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans(spans=[ExpectedSpan(name="main", parent=None, status_code=StatusCode.ERROR)]) + + with pytest.raises(Exception, match="Boom"), driver: + raise Exception("Boom") + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + # Works second time too + with pytest.raises(Exception, match="Boom"), driver: + raise Exception("Boom") + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_observe_exception(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ + ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK), + ExpectedSpan(name="func()", parent="main", status_code=StatusCode.OK), + ExpectedSpan(name="Klass.method()", parent="main", status_code=StatusCode.OK), + ] + ) + + def func(word: str): + return word + " you" + + class Klass: + def method(self, word: str): + return word + " yous" + + instance = Klass() + + with driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + # Works second time too + with driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_context_manager_observe(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ + ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK), + ExpectedSpan(name="func()", parent="main", status_code=StatusCode.OK), + ExpectedSpan(name="Klass.method()", parent="main", status_code=StatusCode.OK), + ] + ) + + def func(word: str): + return word + " you" + + class Klass: + def method(self, word: str): + return word + " yous" + + instance = Klass() + + with driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + # Works second time too + with driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_get_span_id(self, driver): + assert driver.get_span_id() is None + with driver: + # Span ID's returned from GriptapeCloudObservabilityDriver should be valid UUIDs + assert self._is_valid_uuid(driver.get_span_id()) + + def _is_valid_uuid(self, val: str) -> bool: + try: + UUID(str(val)) + return True + except ValueError: + return False + + +class TestGriptapeCloudObservabilityDriverSpanExporter: + @pytest.fixture() + def mock_post(self, mocker): + return mocker.patch("requests.post") + + def test_span_exporter_export(self, mock_post): + exporter = GriptapeCloudObservabilityDriver.SpanExporter( + base_url="http://base-url:1234", + api_key="api-key", + headers={"Authorization": "Bearer api-key"}, + structure_run_id="structure-run-id", + ) + + exporter.export( + [ + ReadableSpan( + name="main", + parent=None, + context=SpanContext(trace_id=1, span_id=2, is_remote=False), + start_time=3000, + end_time=4000, + attributes={"key": "value"}, + ), + ReadableSpan( + name="thing-1", + parent=SpanContext(trace_id=1, span_id=2, is_remote=False), + context=SpanContext(trace_id=1, span_id=3, is_remote=False), + start_time=8000, + end_time=9000, + status=Status(status_code=StatusCode.OK), + ), + ReadableSpan( + name="thing-2", + parent=SpanContext(trace_id=1, span_id=2, is_remote=False), + context=SpanContext(trace_id=1, span_id=3, is_remote=False), + start_time=8000, + end_time=9000, + status=Status(status_code=StatusCode.ERROR), + events=[ + Event( + timestamp=10000, + name="exception", + attributes={ + "exception.type": "Exception", + "exception.message": "Boom", + "exception.stacktrace": "Traceback (most recent call last) ...", + }, + ) + ], + ), + ] + ) + + mock_post.assert_called_once_with( + url="http://base-url:1234/api/structure-runs/structure-run-id/spans", + json=[ + { + "trace_id": "00000000-0000-0000-0000-000000000001", + "span_id": "00000000-0000-0000-0000-000000000002", + "parent_id": None, + "name": "main", + "start_time": "1970-01-01T00:00:00.000003Z", + "end_time": "1970-01-01T00:00:00.000004Z", + "status": "UNSET", + "attributes": {"key": "value"}, + "events": [], + }, + { + "trace_id": "00000000-0000-0000-0000-000000000001", + "span_id": "00000000-0000-0000-0000-000000000003", + "parent_id": "00000000-0000-0000-0000-000000000002", + "name": "thing-1", + "start_time": "1970-01-01T00:00:00.000008Z", + "end_time": "1970-01-01T00:00:00.000009Z", + "status": "OK", + "attributes": {}, + "events": [], + }, + { + "trace_id": "00000000-0000-0000-0000-000000000001", + "span_id": "00000000-0000-0000-0000-000000000003", + "parent_id": "00000000-0000-0000-0000-000000000002", + "name": "thing-2", + "start_time": "1970-01-01T00:00:00.000008Z", + "end_time": "1970-01-01T00:00:00.000009Z", + "status": "ERROR", + "attributes": {}, + "events": [ + { + "timestamp": "1970-01-01T00:00:00.000010Z", + "name": "exception", + "attributes": { + "exception.type": "Exception", + "exception.message": "Boom", + "exception.stacktrace": "Traceback (most recent call last) ...", + }, + } + ], + }, + ], + headers={"Authorization": "Bearer api-key"}, + ) diff --git a/tests/unit/drivers/observability/test_no_op_observability_driver.py b/tests/unit/drivers/observability/test_no_op_observability_driver.py new file mode 100644 index 000000000..3a8cccc8d --- /dev/null +++ b/tests/unit/drivers/observability/test_no_op_observability_driver.py @@ -0,0 +1,32 @@ +from __future__ import annotations + +import pytest + +from griptape.common.observable import Observable +from griptape.drivers.observability.no_op_observability_driver import NoOpObservabilityDriver + + +class TestNoOpObservabilityDriver: + @pytest.fixture() + def driver(self): + return NoOpObservabilityDriver() + + def test_observe(self, driver): + def func(word: str): + return word + " you" + + class Klass: + def method(self, word: str): + return word + " yous" + + instance = Klass() + + with driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + def test_get_span_id(self, driver): + assert driver.get_span_id() is None + + with driver: + assert driver.get_span_id() is None diff --git a/tests/unit/drivers/observability/test_open_telemetry_observability_driver.py b/tests/unit/drivers/observability/test_open_telemetry_observability_driver.py new file mode 100644 index 000000000..b903fb1c9 --- /dev/null +++ b/tests/unit/drivers/observability/test_open_telemetry_observability_driver.py @@ -0,0 +1,197 @@ +from unittest.mock import MagicMock + +import pytest +from opentelemetry.sdk.trace.export import BatchSpanProcessor +from opentelemetry.trace import StatusCode + +from griptape.common import Observable +from griptape.drivers import OpenTelemetryObservabilityDriver +from griptape.observability.observability import Observability +from griptape.structures.agent import Agent +from tests.mocks.mock_prompt_driver import MockPromptDriver +from tests.utils.expected_spans import ExpectedSpan, ExpectedSpans + + +class TestOpenTelemetryObservabilityDriver: + @pytest.fixture() + def mock_span_exporter(self): + return MagicMock() + + @pytest.fixture() + def span_processor(self, mock_span_exporter): + return BatchSpanProcessor(mock_span_exporter) + + @pytest.fixture() + def driver(self, span_processor): + return OpenTelemetryObservabilityDriver(service_name="test", span_processor=span_processor) + + def test_init(self, span_processor): + OpenTelemetryObservabilityDriver(service_name="test", span_processor=span_processor) + + def test_context_manager_pass(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans(spans=[ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK)]) + + with driver: + pass + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + # Works second time too + with driver: + pass + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_context_manager_exception(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ExpectedSpan(name="main", parent=None, status_code=StatusCode.ERROR, exception=Exception("Boom"))] + ) + + with pytest.raises(Exception, match="Boom"), driver: + raise Exception("Boom") + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + # Works second time too + with pytest.raises(Exception, match="Boom"), driver: + raise Exception("Boom") + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_context_manager_observe(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ + ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK), + ExpectedSpan(name="func()", parent="main", status_code=StatusCode.OK), + ExpectedSpan(name="Klass.method()", parent="main", status_code=StatusCode.OK), + ] + ) + + def func(word: str): + return word + " you" + + class Klass: + def method(self, word: str): + return word + " yous" + + instance = Klass() + + with driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + # Works second time too + with driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_context_manager_observe_exception_function(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ + ExpectedSpan(name="main", parent=None, status_code=StatusCode.ERROR, exception=Exception("Boom func")), + ExpectedSpan( + name="func()", parent="main", status_code=StatusCode.ERROR, exception=Exception("Boom func") + ), + ] + ) + + def func(word: str): + raise Exception("Boom func") + + with pytest.raises(Exception, match="Boom func"), driver: + assert driver.observe(Observable.Call(func=func, instance=None, args=["Hi"])) == "Hi you" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + + def test_context_manager_observe_exception_method(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ + ExpectedSpan(name="main", parent=None, status_code=StatusCode.ERROR, exception=Exception("Boom meth")), + ExpectedSpan( + name="Klass.method()", parent="main", status_code=StatusCode.ERROR, exception=Exception("Boom meth") + ), + ] + ) + + class Klass: + def method(self, word: str): + raise Exception("Boom meth") + + instance = Klass() + + # Works second time too + with pytest.raises(Exception, match="Boom meth"), driver: + assert driver.observe(Observable.Call(func=instance.method, instance=instance, args=["Bye"])) == "Bye yous" + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_observability_agent(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ + ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK), + ExpectedSpan(name="Agent.run()", parent="main", status_code=StatusCode.OK), + ExpectedSpan(name="Agent.before_run()", parent="Agent.run()", status_code=StatusCode.OK), + ExpectedSpan(name="Agent.try_run()", parent="Agent.run()", status_code=StatusCode.OK), + ExpectedSpan(name="MockPromptDriver.run()", parent="Agent.try_run()", status_code=StatusCode.OK), + ExpectedSpan(name="Agent.after_run()", parent="Agent.run()", status_code=StatusCode.OK), + ] + ) + + with Observability(observability_driver=driver): + agent = Agent(prompt_driver=MockPromptDriver()) + agent.run("Hi") + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_context_manager_observe_adds_tags_attribute(self, driver, mock_span_exporter): + expected_spans = ExpectedSpans( + spans=[ + ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK), + ExpectedSpan( + name="func()", parent="main", status_code=StatusCode.OK, attributes={"tags": ("Foo.bar()",)} + ), + ] + ) + + def func(word: str): + return word + " you" + + with driver: + assert ( + driver.observe( + Observable.Call(func=func, instance=None, args=["Hi"], decorator_kwargs={"tags": ["Foo.bar()"]}) + ) + == "Hi you" + ) + + assert mock_span_exporter.export.call_count == 1 + mock_span_exporter.export.assert_called_with(expected_spans) + mock_span_exporter.export.reset_mock() + + def test_get_span_id(self, driver): + assert driver.get_span_id() is None + with driver: + span_id = driver.get_span_id() + assert span_id is not None + assert isinstance(span_id, str) diff --git a/tests/unit/observability/__init__.py b/tests/unit/observability/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/unit/observability/test_observability.py b/tests/unit/observability/test_observability.py new file mode 100644 index 000000000..6ed87e6b5 --- /dev/null +++ b/tests/unit/observability/test_observability.py @@ -0,0 +1,50 @@ +from unittest.mock import MagicMock + +import pytest + +import griptape.observability.observability as observability +from griptape.observability.observability import Observability + + +class TestObservability: + @pytest.fixture() + def mock_observability_driver(self): + return MagicMock() + + def test_init(self, mock_observability_driver): + assert observability._global_observability_driver is None + + Observability(observability_driver=mock_observability_driver) + + assert observability._global_observability_driver is None + + def test_context_manager(self, mock_observability_driver): + assert observability._global_observability_driver is None + + with Observability(observability_driver=mock_observability_driver): + assert observability._global_observability_driver is mock_observability_driver + mock_observability_driver.__enter__.assert_called_once_with() + + mock_observability_driver.__exit__.assert_called_once_with(None, None, None) + + assert observability._global_observability_driver is None + + def test_context_manager_exception(self, mock_observability_driver): + assert observability._global_observability_driver is None + + with pytest.raises(Exception, match="Boom") as e: # noqa: PT012, SIM117 + with Observability(observability_driver=mock_observability_driver): + assert observability._global_observability_driver is mock_observability_driver + mock_observability_driver.__enter__.assert_called_once_with() + raise Exception("Boom") + + mock_observability_driver.__exit__.assert_called_once_with(*e._excinfo) + assert observability._global_observability_driver is None + + def test_nested_context_manager_raises_exception(self, mock_observability_driver): + assert observability._global_observability_driver is None + + with pytest.raises(Exception, match="Observability driver already set."), Observability( + observability_driver=mock_observability_driver + ), Observability(observability_driver=mock_observability_driver): + pass diff --git a/tests/utils/expected_spans.py b/tests/utils/expected_spans.py new file mode 100644 index 000000000..98cb645db --- /dev/null +++ b/tests/utils/expected_spans.py @@ -0,0 +1,86 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Optional + +from attrs import define, field +from opentelemetry.trace import SpanKind, StatusCode + +if TYPE_CHECKING: + from collections.abc import Sequence + + from opentelemetry.sdk.trace import ReadableSpan + + +@define +class ExpectedSpan: + name: str = field(kw_only=True) + parent: str = field(kw_only=True) + status_code: StatusCode = field(kw_only=True) + exception: Optional[Exception] = field(default=None, kw_only=True) + attributes: Optional[dict] = field(default=None, kw_only=True) + + +@define +class ExpectedSpans: + spans: list[ExpectedSpan] = field(kw_only=True) + + def __eq__(self, other_spans: Sequence[ReadableSpan]) -> bool: # noqa: C901 + # Has expected spans + span_names = [span.name for span in self.spans] + other_span_names = [span.name for span in other_spans] + if sorted(other_span_names) != sorted(span_names): + raise Exception(f"Expected spans {other_span_names} not found. Found: {span_names}") + + # Has valid trace id + trace_id = other_spans[0].context.trace_id + if not trace_id: + raise Exception(f"Trace id is not set on span {other_spans[0].name}") + + for span in other_spans: + # All have same trace id + if span.context.trace_id != trace_id: + raise Exception(f"Span {span.name} has different trace id than the rest") + + # All have kind set to internal + if span.kind != SpanKind.INTERNAL: + raise Exception(f"Span {span.name} is not of kind INTERNAL") + + other_span_by_name = {span.name: span for span in other_spans} + span_by_name = {span.name: span for span in self.spans} + expected_status_codes = {span.name: span.status_code for span in self.spans} + for span_name, status_code in expected_status_codes.items(): + span = other_span_by_name[span_name] + actual_status_code = span.status.status_code + if actual_status_code != status_code: + raise Exception(f"Span {span_name} has code {actual_status_code} instead of {status_code}") + + exception = span_by_name[span_name].exception + if exception: + event = span.events[0] + exc_type = event.attributes.get("exception.type") + exc_message = event.attributes.get("exception.message") + exc_stacktrace = event.attributes.get("exception.stacktrace") + + if exc_type != "Exception": + raise Exception(f"Span {span_name} does not have exception type Exception") + if exc_message != str(exception): + raise Exception(f"Span {span_name} does not have exception message {exception}") + if not exc_stacktrace: + raise Exception(f"Span {span_name} has no stacktrace") + + expected_parents = {span.name: span.parent for span in self.spans} + for child, parent in expected_parents.items(): + actual_parent = other_span_by_name[child].parent.span_id if other_span_by_name[child].parent else None + expected_parent = parent and other_span_by_name[parent].context.span_id + if actual_parent != expected_parent: + raise Exception(f"Span {child} has wrong parent") + + expected_attributes_by_span_name = {span.name: span.attributes for span in self.spans} + for span_name, expected_attributes in expected_attributes_by_span_name.items(): + other_span = other_span_by_name[span_name] + if expected_attributes is not None and other_span.attributes != expected_attributes: + raise Exception( + f"Span {span_name} has attributes {other_span.attributes} instead of {expected_attributes}" + ) + + return True From 2c86a25365eac8cfa25e3662c228d97800224fbf Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Wed, 17 Jul 2024 14:08:34 -0700 Subject: [PATCH 81/87] Add pep8-naming ruff rule (#993) --- CHANGELOG.md | 1 + docs/griptape-framework/structures/config.md | 2 +- .../dummy_audio_transcription_driver.py | 4 ++-- .../embedding/dummy_embedding_driver.py | 4 ++-- .../dummy_image_generation_driver.py | 10 ++++---- .../image_query/dummy_image_query_driver.py | 4 ++-- .../drivers/prompt/dummy_prompt_driver.py | 6 ++--- .../drivers/prompt/google_prompt_driver.py | 23 +++++++++---------- .../dummy_text_to_speech_driver.py | 4 ++-- .../vector/dummy_vector_store_driver.py | 12 +++++----- .../vector/pgvector_vector_store_driver.py | 7 +++--- .../vector/redis_vector_store_driver.py | 4 ++-- .../markdownify_web_scraper_driver.py | 8 +++---- griptape/exceptions/__init__.py | 4 ++-- griptape/exceptions/dummy_exception.py | 2 +- griptape/loaders/image_loader.py | 6 ++--- griptape/loaders/pdf_loader.py | 4 ++-- griptape/schemas/base_schema.py | 20 ++++++---------- griptape/tokenizers/dummy_tokenizer.py | 4 ++-- griptape/utils/import_utils.py | 4 ++-- pyproject.toml | 1 + .../embedding/test_dummy_embedding_driver.py | 4 ++-- .../test_dummy_image_generation_driver.py | 10 ++++---- .../test_dummy_image_query_driver.py | 4 ++-- .../prompt/test_dummy_prompt_driver.py | 6 ++--- .../vector/test_dummy_vector_store_driver.py | 12 +++++----- tests/unit/tokenizers/test_dummy_tokenizer.py | 6 ++--- 27 files changed, 85 insertions(+), 91 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f636f548a..3ab0563f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: `BaseVectorStoreDriver.query` optional arguments are now keyword-only arguments. - **BREAKING**: `EventListener.publish_event`'s `flush` argument is now a keyword-only argument. - **BREAKING**: `BaseEventListenerDriver.publish_event`'s `flush` argument is now a keyword-only argument. +- **BREAKING**: Renamed `DummyException` to `DummyError` for pep8 naming compliance. - Removed unnecessary `transformers` dependency in `drivers-prompt-huggingface` extra. - Removed unnecessary `huggingface-hub` dependency in `drivers-prompt-huggingface-pipeline` extra. diff --git a/docs/griptape-framework/structures/config.md b/docs/griptape-framework/structures/config.md index 969163bf6..ef4bc4864 100644 --- a/docs/griptape-framework/structures/config.md +++ b/docs/griptape-framework/structures/config.md @@ -111,7 +111,7 @@ agent = Agent(config=CohereStructureConfig(api_key=os.environ["COHERE_API_KEY"]) ### Custom Configs You can create your own [StructureConfig](../../reference/griptape/config/structure_config.md) by overriding relevant Drivers. -The [StructureConfig](../../reference/griptape/config/structure_config.md) class includes "Dummy" Drivers for all types, which throw a [DummyException](../../reference/griptape/exceptions/dummy_exception.md) if invoked without being overridden. +The [StructureConfig](../../reference/griptape/config/structure_config.md) class includes "Dummy" Drivers for all types, which throw a [DummyError](../../reference/griptape/exceptions/dummy_exception.md) if invoked without being overridden. This approach ensures that you are informed through clear error messages if you attempt to use Structures without proper Driver configurations. ```python diff --git a/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py b/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py index 9fc44b4b9..c42b21c19 100644 --- a/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py +++ b/griptape/drivers/audio_transcription/dummy_audio_transcription_driver.py @@ -5,7 +5,7 @@ from attrs import define, field from griptape.drivers import BaseAudioTranscriptionDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError if TYPE_CHECKING: from griptape.artifacts import AudioArtifact, TextArtifact @@ -16,4 +16,4 @@ class DummyAudioTranscriptionDriver(BaseAudioTranscriptionDriver): model: str = field(init=False) def try_run(self, audio: AudioArtifact, prompts: Optional[list] = None) -> TextArtifact: - raise DummyException(__class__.__name__, "try_transcription") + raise DummyError(__class__.__name__, "try_transcription") diff --git a/griptape/drivers/embedding/dummy_embedding_driver.py b/griptape/drivers/embedding/dummy_embedding_driver.py index 09171060e..cac8b2418 100644 --- a/griptape/drivers/embedding/dummy_embedding_driver.py +++ b/griptape/drivers/embedding/dummy_embedding_driver.py @@ -3,7 +3,7 @@ from attrs import define, field from griptape.drivers import BaseEmbeddingDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError @define @@ -11,4 +11,4 @@ class DummyEmbeddingDriver(BaseEmbeddingDriver): model: None = field(init=False, default=None, kw_only=True) def try_embed_chunk(self, chunk: str) -> list[float]: - raise DummyException(__class__.__name__, "try_embed_chunk") + raise DummyError(__class__.__name__, "try_embed_chunk") diff --git a/griptape/drivers/image_generation/dummy_image_generation_driver.py b/griptape/drivers/image_generation/dummy_image_generation_driver.py index 9d668c5b2..ec9346841 100644 --- a/griptape/drivers/image_generation/dummy_image_generation_driver.py +++ b/griptape/drivers/image_generation/dummy_image_generation_driver.py @@ -5,7 +5,7 @@ from attrs import define, field from griptape.drivers import BaseImageGenerationDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError if TYPE_CHECKING: from griptape.artifacts import ImageArtifact @@ -16,7 +16,7 @@ class DummyImageGenerationDriver(BaseImageGenerationDriver): model: None = field(init=False, default=None, kw_only=True) def try_text_to_image(self, prompts: list[str], negative_prompts: Optional[list[str]] = None) -> ImageArtifact: - raise DummyException(__class__.__name__, "try_text_to_image") + raise DummyError(__class__.__name__, "try_text_to_image") def try_image_variation( self, @@ -24,7 +24,7 @@ def try_image_variation( image: ImageArtifact, negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: - raise DummyException(__class__.__name__, "try_image_variation") + raise DummyError(__class__.__name__, "try_image_variation") def try_image_inpainting( self, @@ -33,7 +33,7 @@ def try_image_inpainting( mask: ImageArtifact, negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: - raise DummyException(__class__.__name__, "try_image_inpainting") + raise DummyError(__class__.__name__, "try_image_inpainting") def try_image_outpainting( self, @@ -42,4 +42,4 @@ def try_image_outpainting( mask: ImageArtifact, negative_prompts: Optional[list[str]] = None, ) -> ImageArtifact: - raise DummyException(__class__.__name__, "try_image_outpainting") + raise DummyError(__class__.__name__, "try_image_outpainting") diff --git a/griptape/drivers/image_query/dummy_image_query_driver.py b/griptape/drivers/image_query/dummy_image_query_driver.py index 1df1c4c65..62820efd7 100644 --- a/griptape/drivers/image_query/dummy_image_query_driver.py +++ b/griptape/drivers/image_query/dummy_image_query_driver.py @@ -5,7 +5,7 @@ from attrs import define, field from griptape.drivers import BaseImageQueryDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError if TYPE_CHECKING: from griptape.artifacts import ImageArtifact, TextArtifact @@ -17,4 +17,4 @@ class DummyImageQueryDriver(BaseImageQueryDriver): max_tokens: None = field(init=False, default=None, kw_only=True) def try_query(self, query: str, images: list[ImageArtifact]) -> TextArtifact: - raise DummyException(__class__.__name__, "try_query") + raise DummyError(__class__.__name__, "try_query") diff --git a/griptape/drivers/prompt/dummy_prompt_driver.py b/griptape/drivers/prompt/dummy_prompt_driver.py index 9ed1f45ec..377630531 100644 --- a/griptape/drivers/prompt/dummy_prompt_driver.py +++ b/griptape/drivers/prompt/dummy_prompt_driver.py @@ -6,7 +6,7 @@ from griptape.common import observable from griptape.drivers import BasePromptDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError from griptape.tokenizers import DummyTokenizer if TYPE_CHECKING: @@ -22,8 +22,8 @@ class DummyPromptDriver(BasePromptDriver): @observable def try_run(self, prompt_stack: PromptStack) -> Message: - raise DummyException(__class__.__name__, "try_run") + raise DummyError(__class__.__name__, "try_run") @observable def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: - raise DummyException(__class__.__name__, "try_stream") + raise DummyError(__class__.__name__, "try_stream") diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 3a32ebca7..8256ba6eb 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -113,19 +113,18 @@ def try_stream(self, prompt_stack: PromptStack) -> Iterator[DeltaMessage]: ) def _base_params(self, prompt_stack: PromptStack) -> dict: - GenerationConfig = import_optional_dependency("google.generativeai.types").GenerationConfig - ContentDict = import_optional_dependency("google.generativeai.types").ContentDict - Part = import_optional_dependency("google.generativeai.protos").Part + types = import_optional_dependency("google.generativeai.types") + protos = import_optional_dependency("google.generativeai.protos") system_messages = prompt_stack.system_messages if system_messages: - self.model_client._system_instruction = ContentDict( + self.model_client._system_instruction = types.ContentDict( role="system", - parts=[Part(text=system_message.to_text()) for system_message in system_messages], + parts=[protos.Part(text=system_message.to_text()) for system_message in system_messages], ) return { - "generation_config": GenerationConfig( + "generation_config": types.GenerationConfig( **{ # For some reason, providing stop sequences when streaming breaks native functions # https://github.com/google-gemini/generative-ai-python/issues/446 @@ -153,10 +152,10 @@ def _default_model_client(self) -> GenerativeModel: return genai.GenerativeModel(self.model) def __to_google_messages(self, prompt_stack: PromptStack) -> ContentsType: - ContentDict = import_optional_dependency("google.generativeai.types").ContentDict + types = import_optional_dependency("google.generativeai.types") inputs = [ - ContentDict( + types.ContentDict( { "role": self.__to_google_role(message), "parts": [self.__to_google_message_content(content) for content in message.content], @@ -175,7 +174,7 @@ def __to_google_role(self, message: Message) -> str: return "user" def __to_google_tools(self, tools: list[BaseTool]) -> list[dict]: - FunctionDeclaration = import_optional_dependency("google.generativeai.types").FunctionDeclaration + types = import_optional_dependency("google.generativeai.types") tool_declarations = [] for tool in tools: @@ -186,7 +185,7 @@ def __to_google_tools(self, tools: list[BaseTool]) -> list[dict]: schema = schema["properties"]["values"] schema = remove_key_in_dict_recursively(schema, "additionalProperties") - tool_declaration = FunctionDeclaration( + tool_declaration = types.FunctionDeclaration( name=tool.to_native_tool_name(activity), description=tool.activity_description(activity), parameters={ @@ -201,13 +200,13 @@ def __to_google_tools(self, tools: list[BaseTool]) -> list[dict]: return tool_declarations def __to_google_message_content(self, content: BaseMessageContent) -> ContentDict | Part | str: - ContentDict = import_optional_dependency("google.generativeai.types").ContentDict + types = import_optional_dependency("google.generativeai.types") protos = import_optional_dependency("google.generativeai.protos") if isinstance(content, TextMessageContent): return content.artifact.to_text() elif isinstance(content, ImageMessageContent): - return ContentDict(mime_type=content.artifact.mime_type, data=content.artifact.value) + return types.ContentDict(mime_type=content.artifact.mime_type, data=content.artifact.value) elif isinstance(content, ActionCallMessageContent): action = content.artifact.value diff --git a/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py b/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py index 6472bdff8..0f5842bfe 100644 --- a/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py +++ b/griptape/drivers/text_to_speech/dummy_text_to_speech_driver.py @@ -5,7 +5,7 @@ from attrs import define, field from griptape.drivers import BaseTextToSpeechDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError if TYPE_CHECKING: from griptape.artifacts.audio_artifact import AudioArtifact @@ -16,4 +16,4 @@ class DummyTextToSpeechDriver(BaseTextToSpeechDriver): model: None = field(init=False, default=None, kw_only=True) def try_text_to_audio(self, prompts: list[str]) -> AudioArtifact: - raise DummyException(__class__.__name__, "try_text_to_audio") + raise DummyError(__class__.__name__, "try_text_to_audio") diff --git a/griptape/drivers/vector/dummy_vector_store_driver.py b/griptape/drivers/vector/dummy_vector_store_driver.py index 4dbb6c038..3bbfbd304 100644 --- a/griptape/drivers/vector/dummy_vector_store_driver.py +++ b/griptape/drivers/vector/dummy_vector_store_driver.py @@ -5,7 +5,7 @@ from attrs import Factory, define, field from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError @define() @@ -17,7 +17,7 @@ class DummyVectorStoreDriver(BaseVectorStoreDriver): ) def delete_vector(self, vector_id: str) -> None: - raise DummyException(__class__.__name__, "delete_vector") + raise DummyError(__class__.__name__, "delete_vector") def upsert_vector( self, @@ -27,13 +27,13 @@ def upsert_vector( meta: Optional[dict] = None, **kwargs, ) -> str: - raise DummyException(__class__.__name__, "upsert_vector") + raise DummyError(__class__.__name__, "upsert_vector") def load_entry(self, vector_id: str, *, namespace: Optional[str] = None) -> Optional[BaseVectorStoreDriver.Entry]: - raise DummyException(__class__.__name__, "load_entry") + raise DummyError(__class__.__name__, "load_entry") def load_entries(self, *, namespace: Optional[str] = None) -> list[BaseVectorStoreDriver.Entry]: - raise DummyException(__class__.__name__, "load_entries") + raise DummyError(__class__.__name__, "load_entries") def query( self, @@ -44,4 +44,4 @@ def query( include_vectors: bool = False, **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: - raise DummyException(__class__.__name__, "query") + raise DummyError(__class__.__name__, "query") diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index f82a5e3ac..ec266030a 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -180,15 +180,14 @@ def query( ] def default_vector_model(self) -> Any: - Vector = import_optional_dependency("pgvector.sqlalchemy").Vector - Base = declarative_base() + sqlalchemy = import_optional_dependency("pgvector.sqlalchemy") @dataclass - class VectorModel(Base): + class VectorModel(declarative_base()): __tablename__ = self.table_name id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) - vector = Column(Vector()) + vector = Column(sqlalchemy.Vector()) namespace = Column(String) meta = Column(JSON) diff --git a/griptape/drivers/vector/redis_vector_store_driver.py b/griptape/drivers/vector/redis_vector_store_driver.py index 7d262f05d..06aa853c6 100644 --- a/griptape/drivers/vector/redis_vector_store_driver.py +++ b/griptape/drivers/vector/redis_vector_store_driver.py @@ -124,13 +124,13 @@ def query( Returns: A list of BaseVectorStoreDriver.Entry objects, each encapsulating the retrieved vector, its similarity score, metadata, and namespace. """ - Query = import_optional_dependency("redis.commands.search.query").Query + search_query = import_optional_dependency("redis.commands.search.query") vector = self.embedding_driver.embed_string(query) filter_expression = f"(@namespace:{{{namespace}}})" if namespace else "*" query_expression = ( - Query(f"{filter_expression}=>[KNN {count or 10} @vector $vector as score]") + search_query.Query(f"{filter_expression}=>[KNN {count or 10} @vector $vector as score]") .sort_by("score") .return_fields("id", "score", "metadata", "vec_string") .paging(0, count or 10) diff --git a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py index 6e25ca3b6..556d5e06e 100644 --- a/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py +++ b/griptape/drivers/web_scraper/markdownify_web_scraper_driver.py @@ -40,14 +40,14 @@ class MarkdownifyWebScraperDriver(BaseWebScraperDriver): def scrape_url(self, url: str) -> TextArtifact: sync_playwright = import_optional_dependency("playwright.sync_api").sync_playwright - BeautifulSoup = import_optional_dependency("bs4").BeautifulSoup - MarkdownConverter = import_optional_dependency("markdownify").MarkdownConverter + bs4 = import_optional_dependency("bs4") + markdownify = import_optional_dependency("markdownify") include_links = self.include_links # Custom MarkdownConverter to optionally linked urls. If include_links is False only # the text of the link is returned. - class OptionalLinksMarkdownConverter(MarkdownConverter): + class OptionalLinksMarkdownConverter(markdownify.MarkdownConverter): def convert_a(self, el: Any, text: str, convert_as_inline: Any) -> str: if include_links: return super().convert_a(el, text, convert_as_inline) @@ -75,7 +75,7 @@ def skip_loading_images(route: Any) -> Any: if not content: raise Exception("can't access URL") - soup = BeautifulSoup(content, "html.parser") + soup = bs4.BeautifulSoup(content, "html.parser") # Remove unwanted elements exclude_selector = ",".join( diff --git a/griptape/exceptions/__init__.py b/griptape/exceptions/__init__.py index 5c8e6920b..80d5081ed 100644 --- a/griptape/exceptions/__init__.py +++ b/griptape/exceptions/__init__.py @@ -1,3 +1,3 @@ -from .dummy_exception import DummyException +from .dummy_exception import DummyError -__all__ = ["DummyException"] +__all__ = ["DummyError"] diff --git a/griptape/exceptions/dummy_exception.py b/griptape/exceptions/dummy_exception.py index 3b4de955a..815cb245f 100644 --- a/griptape/exceptions/dummy_exception.py +++ b/griptape/exceptions/dummy_exception.py @@ -1,4 +1,4 @@ -class DummyException(Exception): +class DummyError(Exception): def __init__(self, dummy_class_name: str, dummy_method_name: str) -> None: message = ( f"You have attempted to use a {dummy_class_name}'s {dummy_method_name} method. " diff --git a/griptape/loaders/image_loader.py b/griptape/loaders/image_loader.py index 90048abc1..b7a277edb 100644 --- a/griptape/loaders/image_loader.py +++ b/griptape/loaders/image_loader.py @@ -32,14 +32,14 @@ class ImageLoader(BaseLoader): } def load(self, source: bytes, *args, **kwargs) -> ImageArtifact: - Image = import_optional_dependency("PIL.Image") - image = Image.open(BytesIO(source)) + pil_image = import_optional_dependency("PIL.Image") + image = pil_image.open(BytesIO(source)) # Normalize format only if requested. if self.format is not None: byte_stream = BytesIO() image.save(byte_stream, format=self.format) - image = Image.open(byte_stream) + image = pil_image.open(byte_stream) source = byte_stream.getvalue() image_artifact = ImageArtifact(source, format=image.format.lower(), width=image.width, height=image.height) diff --git a/griptape/loaders/pdf_loader.py b/griptape/loaders/pdf_loader.py index 0dfb959cf..b38e2cd77 100644 --- a/griptape/loaders/pdf_loader.py +++ b/griptape/loaders/pdf_loader.py @@ -27,8 +27,8 @@ def load( *args, **kwargs, ) -> ErrorArtifact | list[TextArtifact]: - PdfReader = import_optional_dependency("pypdf").PdfReader - reader = PdfReader(BytesIO(source), strict=True, password=password) + pypdf = import_optional_dependency("pypdf") + reader = pypdf.PdfReader(BytesIO(source), strict=True, password=password) return self._text_to_artifacts("\n".join([p.extract_text() for p in reader.pages])) def load_collection(self, sources: list[bytes], *args, **kwargs) -> dict[str, ErrorArtifact | list[TextArtifact]]: diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 0bf7c4760..9fd7c22db 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -67,9 +67,9 @@ def _get_field_for_type(cls, field_type: type) -> fields.Field | fields.Nested: else: raise ValueError(f"Missing type for list field: {field_type}") else: - FieldClass = cls.DATACLASS_TYPE_MAPPING[field_class] + field_class = cls.DATACLASS_TYPE_MAPPING[field_class] - return FieldClass(allow_none=optional) + return field_class(allow_none=optional) @classmethod def _get_field_type_info(cls, field_type: type) -> tuple[type, tuple[type, ...], bool]: @@ -131,14 +131,6 @@ def _resolve_types(cls, attrs_cls: type) -> None: from griptape.tools import BaseTool from griptape.utils.import_utils import import_optional_dependency, is_dependency_installed - boto3 = import_optional_dependency("boto3") if is_dependency_installed("boto3") else Any - Client = import_optional_dependency("cohere").Client if is_dependency_installed("cohere") else Any - GenerativeModel = ( - import_optional_dependency("google.generativeai").GenerativeModel - if is_dependency_installed("google.generativeai") - else Any - ) - attrs.resolve_types( attrs_cls, localns={ @@ -163,9 +155,11 @@ def _resolve_types(cls, attrs_cls: type) -> None: "Run": Run, "Sequence": Sequence, # Third party modules - "Client": Client, - "GenerativeModel": GenerativeModel, - "boto3": boto3, + "Client": import_optional_dependency("cohere").Client if is_dependency_installed("cohere") else Any, + "GenerativeModel": import_optional_dependency("google.generativeai").GenerativeModel + if is_dependency_installed("google.generativeai") + else Any, + "boto3": import_optional_dependency("boto3") if is_dependency_installed("boto3") else Any, }, ) diff --git a/griptape/tokenizers/dummy_tokenizer.py b/griptape/tokenizers/dummy_tokenizer.py index b13b1fecb..978d423c0 100644 --- a/griptape/tokenizers/dummy_tokenizer.py +++ b/griptape/tokenizers/dummy_tokenizer.py @@ -4,7 +4,7 @@ from attrs import define, field -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError from griptape.tokenizers import BaseTokenizer @@ -15,4 +15,4 @@ class DummyTokenizer(BaseTokenizer): max_output_tokens: int = field(init=False, default=0, kw_only=True) def count_tokens(self, text: str) -> int: - raise DummyException(__class__.__name__, "count_tokens") + raise DummyError(__class__.__name__, "count_tokens") diff --git a/griptape/utils/import_utils.py b/griptape/utils/import_utils.py index f0a8c205d..ce9173231 100644 --- a/griptape/utils/import_utils.py +++ b/griptape/utils/import_utils.py @@ -1,7 +1,7 @@ from __future__ import annotations from importlib import import_module -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING if TYPE_CHECKING: from types import ModuleType @@ -14,7 +14,7 @@ } -def import_optional_dependency(name: str) -> Optional[ModuleType]: +def import_optional_dependency(name: str) -> ModuleType: """Import an optional dependency. If a dependency is missing, an ImportError with a nice message will be raised. diff --git a/pyproject.toml b/pyproject.toml index 510209d82..1e7a7cf33 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -241,6 +241,7 @@ select = [ "ANN", # flake8-annotations "FBT", # flake8-boolean-trap "PT", # flake8-pytest-style + "N" # pep8-naming ] ignore = [ "UP007", # non-pep604-annotation diff --git a/tests/unit/drivers/embedding/test_dummy_embedding_driver.py b/tests/unit/drivers/embedding/test_dummy_embedding_driver.py index af56ce6ac..bafb4fc9a 100644 --- a/tests/unit/drivers/embedding/test_dummy_embedding_driver.py +++ b/tests/unit/drivers/embedding/test_dummy_embedding_driver.py @@ -1,7 +1,7 @@ import pytest from griptape.drivers import DummyEmbeddingDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError class TestDummyEmbeddingDriver: @@ -13,5 +13,5 @@ def test_init(self, embedding_driver): assert embedding_driver def test_try_embed_chunk(self, embedding_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): embedding_driver.try_embed_chunk("prompt-stack") diff --git a/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py b/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py index 2df6c6499..118bd778a 100644 --- a/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py +++ b/tests/unit/drivers/image_generation/test_dummy_image_generation_driver.py @@ -2,7 +2,7 @@ from griptape.artifacts import ImageArtifact from griptape.drivers import DummyImageGenerationDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError class TestDummyImageGenerationDriver: @@ -14,11 +14,11 @@ def test_init(self, image_generation_driver): assert image_generation_driver def test_text_to_image(self, image_generation_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): image_generation_driver.try_text_to_image("prompt-stack") def test_try_image_variation(self, image_generation_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): image_generation_driver.try_image_variation( "prompt-stack", ImageArtifact(value=b"", width=100, height=100, format="png"), @@ -26,7 +26,7 @@ def test_try_image_variation(self, image_generation_driver): ) def test_try_image_inpainting(self, image_generation_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): image_generation_driver.try_image_inpainting( "prompt-stack", ImageArtifact(value=b"", width=100, height=100, format="png"), @@ -34,7 +34,7 @@ def test_try_image_inpainting(self, image_generation_driver): ) def test_try_image_outpainting(self, image_generation_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): image_generation_driver.try_image_outpainting( "prompt-stack", ImageArtifact(value=b"", width=100, height=100, format="png"), diff --git a/tests/unit/drivers/image_query/test_dummy_image_query_driver.py b/tests/unit/drivers/image_query/test_dummy_image_query_driver.py index 02b69595f..9da59c435 100644 --- a/tests/unit/drivers/image_query/test_dummy_image_query_driver.py +++ b/tests/unit/drivers/image_query/test_dummy_image_query_driver.py @@ -2,7 +2,7 @@ from griptape.artifacts import ImageArtifact from griptape.drivers import DummyImageQueryDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError class TestDummyImageQueryDriver: @@ -14,5 +14,5 @@ def test_init(self, image_query_driver): assert image_query_driver def test_try_query(self, image_query_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): image_query_driver.try_query("Prompt", [ImageArtifact(value=b"", width=100, height=100, format="png")]) diff --git a/tests/unit/drivers/prompt/test_dummy_prompt_driver.py b/tests/unit/drivers/prompt/test_dummy_prompt_driver.py index 203bad3d5..2758b909b 100644 --- a/tests/unit/drivers/prompt/test_dummy_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_dummy_prompt_driver.py @@ -1,7 +1,7 @@ import pytest from griptape.drivers import DummyPromptDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError class TestDummyPromptDriver: @@ -13,9 +13,9 @@ def test_init(self, prompt_driver): assert prompt_driver def test_try_run(self, prompt_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): prompt_driver.try_run("prompt-stack") def test_try_stream_run(self, prompt_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): prompt_driver.try_run("prompt-stack") diff --git a/tests/unit/drivers/vector/test_dummy_vector_store_driver.py b/tests/unit/drivers/vector/test_dummy_vector_store_driver.py index df4867212..3cde52ebc 100644 --- a/tests/unit/drivers/vector/test_dummy_vector_store_driver.py +++ b/tests/unit/drivers/vector/test_dummy_vector_store_driver.py @@ -1,7 +1,7 @@ import pytest from griptape.drivers import DummyVectorStoreDriver -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError class TestDummyVectorStoreDriver: @@ -10,21 +10,21 @@ def vector_store_driver(self): return DummyVectorStoreDriver() def test_delete_vector(self, vector_store_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): vector_store_driver.delete_vector("foo bar huzzah") def test_upsert_vector(self, vector_store_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): vector_store_driver.upsert_vector("foo bar huzzah") def test_load_entry(self, vector_store_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): vector_store_driver.load_entry("foo bar huzzah") def test_load_entries(self, vector_store_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): vector_store_driver.load_entries(namespace="foo bar huzzah") def test_query(self, vector_store_driver): - with pytest.raises(DummyException): + with pytest.raises(DummyError): vector_store_driver.query("foo bar huzzah") diff --git a/tests/unit/tokenizers/test_dummy_tokenizer.py b/tests/unit/tokenizers/test_dummy_tokenizer.py index 5d770d1aa..7edfd6e40 100644 --- a/tests/unit/tokenizers/test_dummy_tokenizer.py +++ b/tests/unit/tokenizers/test_dummy_tokenizer.py @@ -1,6 +1,6 @@ import pytest -from griptape.exceptions import DummyException +from griptape.exceptions import DummyError from griptape.tokenizers import DummyTokenizer @@ -10,9 +10,9 @@ def tokenizer(self): return DummyTokenizer() def test_token_count(self, tokenizer): - with pytest.raises(DummyException): + with pytest.raises(DummyError): tokenizer.count_tokens("foo bar huzzah") def test_tokens_left(self, tokenizer): - with pytest.raises(DummyException): + with pytest.raises(DummyError): tokenizer.count_tokens("foo bar huzzah") From 362fac0be9fb869c947e974c2ff8734fd5b8633c Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 18 Jul 2024 09:46:09 -0700 Subject: [PATCH 82/87] Add generic artifact (#983) --- CHANGELOG.md | 1 + docs/examples/talk-to-a-video.md | 77 ++++++++++++++++++ griptape/artifacts/__init__.py | 2 + griptape/artifacts/generic_artifact.py | 15 ++++ griptape/common/__init__.py | 2 + .../contents/generic_message_content.py | 21 +++++ griptape/common/prompt_stack/prompt_stack.py | 5 +- .../drivers/prompt/google_prompt_driver.py | 4 +- griptape/schemas/base_schema.py | 16 ++-- griptape/tasks/prompt_task.py | 2 + mkdocs.yml | 1 + tests/resources/griptape-comfyui.mp4 | Bin 0 -> 4667824 bytes tests/unit/artifacts/test_generic_artifact.py | 27 ++++++ tests/unit/common/test_prompt_stack.py | 11 ++- .../prompt/test_google_prompt_driver.py | 4 +- 15 files changed, 178 insertions(+), 10 deletions(-) create mode 100644 docs/examples/talk-to-a-video.md create mode 100644 griptape/artifacts/generic_artifact.py create mode 100644 griptape/common/prompt_stack/contents/generic_message_content.py create mode 100644 tests/resources/griptape-comfyui.mp4 create mode 100644 tests/unit/artifacts/test_generic_artifact.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ab0563f3..79e3dd5db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `GriptapeCloudObservabilityDriver` for sending observability data to Griptape Cloud. - `Observability` context manager for enabling observability and configuring which Observability Driver to use. - `@observable` decorator for selecting which functions/methods to provide observability for. +- `GenericArtifact` for storing any data. ### Changed - **BREAKING**: `BaseVectorStoreDriver.upsert_text_artifacts` optional arguments are now keyword-only arguments. diff --git a/docs/examples/talk-to-a-video.md b/docs/examples/talk-to-a-video.md new file mode 100644 index 000000000..9673bd1c3 --- /dev/null +++ b/docs/examples/talk-to-a-video.md @@ -0,0 +1,77 @@ +We can use Google Gemini's [native video input](https://ai.google.dev/gemini-api/docs/vision?lang=python#prompting-video) capabilities to ask questions about [a video](https://www.youtube.com/watch?v=XXuIBHO4qa8). +In this example, we upload a video file using Gemini's file API, and then pass the result using the [GenericArtifact](../reference/griptape/artifacts/generic_artifact.md) to the Agent. +Note that because we are using Gemini-specific features, this will not work with other [Prompt Drivers](../griptape-framework/drivers/prompt-drivers.md). + +```python +import time +from griptape.structures import Agent +from griptape.tasks import PromptTask +from griptape.artifacts import GenericArtifact, TextArtifact +from griptape.config import GoogleStructureConfig +import google.generativeai as genai + +video_file = genai.upload_file(path="tests/resources/griptape-comfyui.mp4") +while video_file.state.name == "PROCESSING": + time.sleep(2) + video_file = genai.get_file(video_file.name) + +if video_file.state.name == "FAILED": + raise ValueError(video_file.state.name) + +agent = Agent( + config=GoogleStructureConfig(), + input=[ + GenericArtifact(video_file), + TextArtifact("Answer this question regarding the video: {{ args[0] }}"), + ] +) + +agent.run("Are there any scenes that show a character with earings?") +agent.run("What happens in the scene starting at 19 seconds?") +``` + +``` +[07/15/24 11:27:17] INFO PromptTask 765a4a2833a34084b0077fb49c948ace + Input: genai.File({ + 'name': 'files/zzqllezrzmz7', + 'display_name': 'griptape-comfyui.mp4', + 'mime_type': 'video/mp4', + 'sha256_hash': 'ODk5ZDIxMzQwMGZjYTJkNWU3OTY3YjgzZmUxNzg1ZTNmYzc2YTAxMzgxMWIzYWQyMTBjNzM4ODc5MjU1ZmFmNQ==', + 'size_bytes': '4667824', + 'state': 'ACTIVE', + 'uri': 'https://generativelanguage.googleapis.com/v1beta/files/zzqllezrzmz7', + 'video_metadata': {'video_duration': '36s'}, + 'create_time': '2024-07-15T18:27:14.692475Z', + 'expiration_time': '2024-07-17T18:27:14.625351853Z', + 'update_time': '2024-07-15T18:27:16.179456Z'}) + + Are there any scenes that show a character with earings? +[07/15/24 11:27:21] INFO PromptTask 765a4a2833a34084b0077fb49c948ace + Output: Yes, there are a few scenes that show characters with earrings: + + * **0:10-0:15:** A woman with short, dark hair and facial tattoos is shown wearing large hoop earrings. + * **0:23:** A woman with short, dark hair and facial tattoos is shown wearing large hoop earrings. + + Let me know if you have any other questions about the video! + + INFO PromptTask 765a4a2833a34084b0077fb49c948ace + Input: genai.File({ + 'name': 'files/zzqllezrzmz7', + 'display_name': 'griptape-comfyui.mp4', + 'mime_type': 'video/mp4', + 'sha256_hash': 'ODk5ZDIxMzQwMGZjYTJkNWU3OTY3YjgzZmUxNzg1ZTNmYzc2YTAxMzgxMWIzYWQyMTBjNzM4ODc5MjU1ZmFmNQ==', + 'size_bytes': '4667824', + 'state': 'ACTIVE', + 'uri': 'https://generativelanguage.googleapis.com/v1beta/files/zzqllezrzmz7', + 'video_metadata': {'video_duration': '36s'}, + 'create_time': '2024-07-15T18:27:14.692475Z', + 'expiration_time': '2024-07-17T18:27:14.625351853Z', + 'update_time': '2024-07-15T18:27:16.179456Z'}) + + What happens in the scene starting at 19 seconds? +[07/15/24 11:27:26] INFO PromptTask 765a4a2833a34084b0077fb49c948ace + Output: At 19 seconds, a futuristic, four-legged robotic vehicle descends from the sky in a misty forest. The vehicle resembles a mechanical + spider or insect, with a rounded central body and powerful-looking legs. It hovers slightly above the ground, emitting two bright beams of + light from its underside. The scene has a slightly eerie and mysterious atmosphere, with the fog and bare trees adding to the sense of + otherworldliness. +``` diff --git a/griptape/artifacts/__init__.py b/griptape/artifacts/__init__.py index 51525f60d..e9fc6daba 100644 --- a/griptape/artifacts/__init__.py +++ b/griptape/artifacts/__init__.py @@ -10,6 +10,7 @@ from .image_artifact import ImageArtifact from .audio_artifact import AudioArtifact from .action_artifact import ActionArtifact +from .generic_artifact import GenericArtifact __all__ = [ @@ -25,4 +26,5 @@ "ImageArtifact", "AudioArtifact", "ActionArtifact", + "GenericArtifact", ] diff --git a/griptape/artifacts/generic_artifact.py b/griptape/artifacts/generic_artifact.py new file mode 100644 index 000000000..8e0b7e38c --- /dev/null +++ b/griptape/artifacts/generic_artifact.py @@ -0,0 +1,15 @@ +from __future__ import annotations + +from typing import Any + +from attrs import define, field + +from griptape.artifacts import BaseArtifact + + +@define +class GenericArtifact(BaseArtifact): + value: Any = field(metadata={"serializable": True}) + + def __add__(self, other: BaseArtifact) -> BaseArtifact: + raise NotImplementedError diff --git a/griptape/common/__init__.py b/griptape/common/__init__.py index 6ceff61eb..6ac434649 100644 --- a/griptape/common/__init__.py +++ b/griptape/common/__init__.py @@ -9,6 +9,7 @@ from .prompt_stack.contents.action_call_delta_message_content import ActionCallDeltaMessageContent from .prompt_stack.contents.action_call_message_content import ActionCallMessageContent from .prompt_stack.contents.action_result_message_content import ActionResultMessageContent +from .prompt_stack.contents.generic_message_content import GenericMessageContent from .prompt_stack.messages.base_message import BaseMessage from .prompt_stack.messages.delta_message import DeltaMessage @@ -29,6 +30,7 @@ "TextDeltaMessageContent", "TextMessageContent", "ImageMessageContent", + "GenericMessageContent", "ActionCallDeltaMessageContent", "ActionCallMessageContent", "ActionResultMessageContent", diff --git a/griptape/common/prompt_stack/contents/generic_message_content.py b/griptape/common/prompt_stack/contents/generic_message_content.py new file mode 100644 index 000000000..453b52df9 --- /dev/null +++ b/griptape/common/prompt_stack/contents/generic_message_content.py @@ -0,0 +1,21 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +from attrs import define, field + +from griptape.common import BaseDeltaMessageContent, BaseMessageContent + +if TYPE_CHECKING: + from collections.abc import Sequence + + from griptape.artifacts import GenericArtifact + + +@define +class GenericMessageContent(BaseMessageContent): + artifact: GenericArtifact = field(metadata={"serializable": True}) + + @classmethod + def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> GenericMessageContent: + raise NotImplementedError() diff --git a/griptape/common/prompt_stack/prompt_stack.py b/griptape/common/prompt_stack/prompt_stack.py index 8bbe98161..3186dac89 100644 --- a/griptape/common/prompt_stack/prompt_stack.py +++ b/griptape/common/prompt_stack/prompt_stack.py @@ -4,11 +4,12 @@ from attrs import define, field -from griptape.artifacts import ActionArtifact, BaseArtifact, ImageArtifact, ListArtifact, TextArtifact +from griptape.artifacts import ActionArtifact, BaseArtifact, GenericArtifact, ImageArtifact, ListArtifact, TextArtifact from griptape.common import ( ActionCallMessageContent, ActionResultMessageContent, BaseMessageContent, + GenericMessageContent, ImageMessageContent, Message, TextMessageContent, @@ -59,6 +60,8 @@ def __to_message_content(self, artifact: str | BaseArtifact) -> list[BaseMessage return [TextMessageContent(artifact)] elif isinstance(artifact, ImageArtifact): return [ImageMessageContent(artifact)] + elif isinstance(artifact, GenericArtifact): + return [GenericMessageContent(artifact)] elif isinstance(artifact, ActionArtifact): action = artifact.value output = action.output diff --git a/griptape/drivers/prompt/google_prompt_driver.py b/griptape/drivers/prompt/google_prompt_driver.py index 8256ba6eb..06f9dfbe6 100644 --- a/griptape/drivers/prompt/google_prompt_driver.py +++ b/griptape/drivers/prompt/google_prompt_driver.py @@ -14,6 +14,7 @@ BaseDeltaMessageContent, BaseMessageContent, DeltaMessage, + GenericMessageContent, ImageMessageContent, Message, PromptStack, @@ -220,7 +221,8 @@ def __to_google_message_content(self, content: BaseMessageContent) -> ContentDic response=artifact.to_dict(), ), ) - + elif isinstance(content, GenericMessageContent): + return content.artifact.value else: raise ValueError(f"Unsupported prompt stack content type: {type(content)}") diff --git a/griptape/schemas/base_schema.py b/griptape/schemas/base_schema.py index 9fd7c22db..728fdb34f 100644 --- a/griptape/schemas/base_schema.py +++ b/griptape/schemas/base_schema.py @@ -2,7 +2,7 @@ from abc import ABC from collections.abc import Sequence -from typing import Any, Literal, Union, get_args, get_origin +from typing import Any, Literal, Union, _SpecialForm, get_args, get_origin import attrs from marshmallow import INCLUDE, Schema, fields @@ -14,7 +14,7 @@ class BaseSchema(Schema): class Meta: unknown = INCLUDE - DATACLASS_TYPE_MAPPING = {**Schema.TYPE_MAPPING, dict: fields.Dict, bytes: Bytes} + DATACLASS_TYPE_MAPPING = {**Schema.TYPE_MAPPING, dict: fields.Dict, bytes: Bytes, Any: fields.Raw} @classmethod def from_attrs_cls(cls, attrs_cls: type) -> type: @@ -134,6 +134,7 @@ def _resolve_types(cls, attrs_cls: type) -> None: attrs.resolve_types( attrs_cls, localns={ + "Any": Any, "BasePromptDriver": BasePromptDriver, "BaseImageQueryDriver": BaseImageQueryDriver, "BaseEmbeddingDriver": BaseEmbeddingDriver, @@ -164,8 +165,11 @@ def _resolve_types(cls, attrs_cls: type) -> None: ) @classmethod - def is_list_sequence(cls, field_type: type) -> bool: - if issubclass(field_type, str) or issubclass(field_type, bytes) or issubclass(field_type, tuple): - return False + def is_list_sequence(cls, field_type: type | _SpecialForm) -> bool: + if isinstance(field_type, type): + if issubclass(field_type, str) or issubclass(field_type, bytes) or issubclass(field_type, tuple): + return False + else: + return issubclass(field_type, Sequence) else: - return issubclass(field_type, Sequence) + return False diff --git a/griptape/tasks/prompt_task.py b/griptape/tasks/prompt_task.py index 45511875f..350ca4ce0 100644 --- a/griptape/tasks/prompt_task.py +++ b/griptape/tasks/prompt_task.py @@ -103,6 +103,8 @@ def _process_task_input( return task_input elif isinstance(task_input, Callable): return self._process_task_input(task_input(self)) + elif isinstance(task_input, ListArtifact): + return ListArtifact([self._process_task_input(elem) for elem in task_input.value]) elif isinstance(task_input, BaseArtifact): return task_input elif isinstance(task_input, (list, tuple)): diff --git a/mkdocs.yml b/mkdocs.yml index 337b75f31..5c603e4d6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -160,6 +160,7 @@ nav: - Talk to Redshift: "examples/talk-to-redshift.md" - Talk to a Webpage: "examples/talk-to-a-webpage.md" - Talk to a PDF: "examples/talk-to-a-pdf.md" + - Talk to a Video: "examples/talk-to-a-video.md" - Multi Agent Workflows: "examples/multi-agent-workflow.md" - Shared Memory Between Agents: "examples/multiple-agent-shared-memory.md" - Chat Sessions with Amazon DynamoDB: "examples/amazon-dynamodb-sessions.md" diff --git a/tests/resources/griptape-comfyui.mp4 b/tests/resources/griptape-comfyui.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..e0f18e8f5f3fa576804061b7c7a8c0625fb2da9b GIT binary patch literal 4667824 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

iqM4r_VU3*PMpkVq( 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

s~b>MtUf+_(; zvGrie9w-zz)19D|Qa1;=e#TAHRThI-hVi<|&TPX%y3^x@gvE!rtp*6V2bR5I~`_=09lKk+(PyR+^EwV&y z6riqcagsxI_PD|kJ2m}%oG7fE6U|fnv^b&~ROw&N7+xuvEz9_ROKr+_a$-4Xn-12W z5~+$C1ANTy_@L{2jY}G8RMkVDHbUechh((`?M2-#AFZvUQyQuO`nXxEduRB1@ z!x(v+{ZXOXPgvwCrbSswiYR5JcBa_TH?bV9k2eotR=uS`IV!L*wzW2OHt07RBNJn{ zH$Ka8>RS91s z@rr<{Ay4;CrvVm+haT!1+djeZC6h_l9h=ggw{fE)p&|@eQONkTk_`N~r(uf5h)pOh zVCOY08K3_2m&R<3JR8^ERE>N=W#g`hva;3@{E0qaC}(gzO2f$^6IpI7lELE-_u?FX z$ZF`>1jIHslHZkW+572wHCtd8yB=dhH2wwuUNmlZO>`0yn2ff!XL*iTJ z&G|E{isC8F9dR%4r%IazeyyM2rs-jUhW}ONBS7h{hAf*2o2$o!-vg7|z_RrB8W5M{ zF8eU|WXuqXapGIE^XMNO6>3;!O-70k62w?qNeSTcHY9t@Rnw+=FF}6JFtaaYwApH(@lW>@$`0e#lhYhQw2RAH1s2pEGLt4%u0?-SUG(Z+y>;Bi`%9XV5KqX81Q4A)q| z5HzPBWk3d2O{&}BSS0Eq*>45sc`q}?#tcpaeM8K1+)V4Mv4}xJ(oz&DFW2{ccczMt zBrXn9##Pq_b}h zoL<1Xzk2e-#8mTY7$U@je-W0~u{CDbzy>b>Kx<;BjquIuw~NY%la?|sWv(mfteazz z518|DJsC5z{>gipz(kV#Fjl4kR$xW2l(y}Sx$hY;%(bS*!Td*!RQ*X8Ny zv@Xy&=L!YY*re5_D$lF7x0NB3pg%^U?oX)23+bRg+Wx_dC_w zWu1AoHrsjLHHtH-0Ho*^Gh$uc`;c$_Q)Qo!?>~2qvQ&^PJA3TXFoBfdLmmWB+T0c$ zuQtLu(<%0otqk>R(6%7kFwax~Cz#17dhm8Wga+@BHwh{}{~ULZ@I}U3LnTv(;nflRO zZw~5PA?H+*i!0BLv{uA%t_z#yxvYTru#byV>KQB?U#Zc4HuVqJiZ$vS*K=!7;uwO$ z^$NY#g8b2t3?sT9q2nbV>5D_bdMzu1A(7C`#m?^ErU@Y3bcYhze9U44QCI$yB3P;& zt6%<`KrhhWg}o*yh@NHlUp>>jVyI@6PXY7DhS1^xJb`~92{kOOb0{QxWR44jnM&zLYqt?Tw@HPxT%g0>UeB|$~LO1Nv9 zN8f<`WeDddRjP3NSWGfC$p(!9+Y~qr?Vfl zv+$T{$CrACSMkGARHX8a?!vK0{aB4MCtz@6q*v4EkBMUsv9VdSMw$EZ(sVM9RTo>s zd7JBslyHSh+m|RgQK~fOQqFqtTfL*;v z`g37|Rq?ad#l6h%rzv5vsjq!_`5br?`!HdTGM3;T#UyG^&j=8V%-87n?1@Ie#l#0# zg3}!5^6Z?q4OL1qJ;B>0cLXU2h1wVDXu53Rv~(< zbf+3Ca-bi)IQ+cBP@Xu#!jF5o^9>4D!GnPobE0{ zFJ=ieE||FtdVHc~!BA{dy)!(J`rL>IYewsH-e^$00N)G~6fy;f>sgly(wXQO+n~zV z6^U$~zhs9Ebri&fE#Z7~*Xu->9i_^;gq>a4js^`YR#+bW^OXT?dlisxriH{@a7QF44k$hd zQOfo>#DHp6IE@a#w;gVr@Sm3W`ff(+56bQiP7XF5)X^n7>#$3IaWxqhxwKXOYB9xH znB5|)9goDViN4(5%4<306z{IaK3gU#^LB0`rjzdYKJ9n5XGHLozr=#EQ6?DD){!V~JG@58#tD)(W6^yd zhy)evLw(~b>bR)&k7NM}zIfb#2t9O{0yJ1Ut&C+nni$3zK> z6(1=;)+{rJTL__8fAqNM0aukAd$Y|UQKbs})c1_w3`Moptn%@C`)DUJ6<5eot2iM& z?h)~Cco(IU(r6Fa{TRC=@``+$pp6_*MlGC_Bv;H8plgDckZU6{LY=9_{Uk@?7Dmag zz#@BNV3A@(kXQKY=M}g~N0(J`m(A_;PC?~JOHtEfQjDD^$ZzGL^O*)Zo@ag32GhZp zM47_qr5!C(0E|%ysZLVgM+aZ=o1`ri;tNvl$PnVmzyd9{Bziv3f)A9*@8ZSpUaCsK zHd#z+bDO+x0o>$vV&+s1GJ*KRvxRCA{WGuB!4I1nZOnD(JcTF6Y=Y3h`@$va`E=gR za8sl#LfDppi)SP;wsBi@vL8qO=qJ}@UQ0jhrwam&ixS@|Vgse%n6`X;d2(ot{kVMv z7Df#CR~aMvcxi;-fo@GNU6UaQvoZSVSF*wzw_<*ViVDIQ8$5k6h8djSp+&_UscMg9!t-a0|vv z3_O7uN8dF_-o(RM$uYH%#qoGzV9>*T=a~n2XW^4cF!QNO3mQEr2Fg>v9{R5Pm{5ck zb0J5Uke!t2b@iu|Tl0C=^_D$1sNdJ+ua!~qa3`|Vc{`n)4*LYGi29D{EVHy6)*hqE ztNlDBf(nfZ5n#6z%1?=^L!15aN|G`X)EMALC7b!$rEw5Ilt>8j31BfKl&r)zasJA& z=29)y>>RN}6^{ZHisq5nSi%ir`7{_v_0HJB@Bp{J^`x1_uE6A8VIk0xL^Gvkn7}?N7sbp8wR2v~F#RU-1?Hke35g#<0 z2%|{<8=V6>8T+uS@cfz}<1}zMYJiP!@V7S<2f1m)s+tOv54<|LcGYMuPyAd5V`PW6 zyo_kt&stTBq#-kd!+@)DAzSZeiJE3+5o4wUHtuCGC{D1awN4ApZmru*KA%=Czgqhq@iS1s)%@ zqUTRsm}7iIn)kzIdZb;XDSWEByJqMcQ6l_ZX00&w!a9=R`W;G$LL>Jtngt=F3EsRD zBA-T?X-*W0LwZLC8`47e7!y9q=yCUJ)}vW^cbmwol2Mf8U{xSghlaYz9m5~v;cfog zmLx=7c@BLN2LQlbBj&L~S2wv;x9hbLD(=t-4C08B>Jo3IoX%o1acOvTBAsu%>;7w5 z81-tghePuYlGpxdP+>$J^B?^xQl|Z5LSXmE18WVk^F;m`VE7uFd|u`g=hMeDZUfuG zBWA`eMZ&D37u~9dPn>rw%s#0Q{GOl?QRd0NhWosYRm4F?00jJ1xG8tupY$}_nttOT z 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 z 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�!I=qsQ86JXGvhSvsyegWT#n8nA=vV?FV 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�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≠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

ok-IJJ7TenPF{ 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

jRyto@mi#MM8- zxDM_>jH%HduKK;;j9c43LM&&1<4+z7Qs9@PCcV-hnlC*@&k?$*vKV%O=Zq6srd30Q ztP?)PGV|ER3AR1~uf){DhLavd^V{IGZDpv$l#Q&apX;MiUOC;d-#5tZU9#%_w0KLe zvWY*>SlCOxO!xp`2|jA!Nls(;$!TeYZSU5{?M)1W?ybiklE#D#s%5~Vt6%@&CEBxg zu0gkrt#i&K;o4zX{|S*+Lq^R5r$FX*che9y_1n48RTB&{MiJd|qxHJ6g>Y|`69KY` zYWm@1CE&a?ED9B>{%fjm{R^ZB^&3~%K8~-IG4zLeH$9x%@!BC_3+{$`#z#g%6fH## zxX)vkE>bGDZS;1oJ~Lfy)_Gm`QIZ`%wPucQ~F2pi)TgC z8xi63JP;A?jhS#Y*zQuzWT-=^=|=tA!Qzd{ubTa$km;c`_Lw7s*n<}rba=3$skw=# z@dzGRxaR0RWL!50*0qfnsZahO8yri*kTe4i`at?u~%1m zs_wTF(3q%FjEO*P&a+j*%tTONs%alpeI(MPvB@RnR|ZT#9=>q&H&ZBYes$Q3B}S&A zwgt*{@P_mW&{qhpezM?MabpZBFv%)Ra<8FB?8LX)9LT({0>#}+ve1HAh zeP8I*cK(J-^f~*7DF$v9_y4?Bsrn9|^IIMC9rS)eb0wtKO5wwV5R+Lt8DXhpzhlY$ zc6VxHfJ@HbOVj2vk&E=P`wc76K^OY}@a3z+PH;CTY1-}aJG6UsKx$c-1&Lq(_;^R7 z!8Wq65eYUK$q|ob!-3&wp_*;gja07{=78myg%}ZD;Zl;2-+GLX((R>_Z3M$WXr*vhl*LbZFBH)Kc|7$VLp{IDUE6n<)m0}?V9sfsObV2&d0k;CK-6@vKVDqHKeF5h-IY-vk^t%*np z8rtbNyOp$;$`9nAb=}zBuiA9;lIz}Bn7W~8ZxC@jD6SIT8N&y83t8cU0q$KfwlfAF z8=!y%E&at6_Q1=&Q=7_?Nv7?kJO73*uFnU8ERj?A-9{?07M|C*YBFuvBMkz*)~Y*+ zo79Qcvlw$7-|>_(3vi?ZxEi;>Z^T+`uCke|Yoym_FZvew<-p=t=w-}vsq6sV6n>zB zWs$#iDyYkfU2M6_=aq)rQBtHUzMsSDwD)Y)7qB`a?iKr9Z# zz<6boZo|_FN{}Rkr|kU2AeI z!51ufLi9dQ_JGHOVFPkXK^2f%2XjR^`g#}2=8SdaKOGkP_d0*7F#0`=o@znI#gWjC z6EQ3D6Op%Go~R-a>Htp-?pajI3&l8C#O~^*(Z4?@uDDtJmv=87LM~IbfQxt@$>>r@ zjzNlvw8Mag$^+h*6F=VVL}jN?Y?(^P`>J=Mt!v@%#J9OjyG<{|B(X(5=~Hz#_cH7r z?pSY!@udG$5B9N%4!EBD#vw@H-v~BUPf8$5mEM&NI_rDEABZI7(sJk~2CNPWU$l$M z*~dR0Xti7uFO)s5%AK3$x5YRp=ubNZM_Ug1_wPAP`fe$-ODY=XL#w|e1VQWVGG8&X zlasmAijapagN8%;9u$2$rOOdf}_t4PpAGR zT)@=yYq==*EO%7qMY`w9$Akv9siJjA6n)Z_YAewXF{wjjjkjn( z1?%uhN9pZVHEUIQb%(lgjn@^en7PC7yCr-33iB!R)zolH5dCPLjWXf!)=tCdo>_3> zCnF^O>m`0&-R})ya0rptBsIXga&)<4({Cge+n>Ld(IgAI(r zB7ROD9J}vLVpi7SU#7tuSD5}UY|x>;nQ9vM$rclf!dYuyT^N-3wBlk{KqK?P8KQhI zPzLc_rmF6)%<1wN9kpw;u>J`_4JrukzQ{(yRJ~)YFg(ZzycABypxCMpg7E)7 zI;@7@2qR$m*>;2a7z_L0N@E-w%~u9Q@Bf4X{EpXngh}q}mr@KZv~poRfAXk-LpF9$ zryaBBHAz}dCr+j>NZo!0d|DHwtW^nev?qblp$+NtRAV|$FVn;$3vFBHUjGAQ11Pnn zuWpoA;1lx$ajFMY5NQGEZ0bIX5@vmu(!S#&?{ksUI4|#7r&HkeGRhY77@uMdVTvs* zGWrr<<*&4#`yP?U=rp+;+|=iZl9uo`+AE8-8ukh14b@+ncv(9513~Qt`Ocr&nRqb~ zeCsNx@x2Dp%YPFGQ0os}aucTGSdTod$jNj^A>n3?^iZDad!87%<%NOK%3(!_@xc(O z8&c({QK1&5DtYn|wrdrTC}Qcp**~_y|4U&2w5H=xE7vB5c@6Ci1+poZh?k%YBw*Uq`z3VhgF=>atO-b@Q1V2JfR%QGlajOMJc) z@S^2@^=d8mQt!+D0868cGP0+KMu`iaZDcY21u_^u zPpVe!EaLN&YO&CF1udYTe|&kyv{0x>5@9YZ$6ANeVF1p=ULj-w+as*cSIld}Dq2mu z=wYY7lhA=ymXOS*3=AfTVimt+EgSsVCP#X{WaisKqj{dQdNh9bzVu8FblQX#7m4^g z5oWP8nc|5=3O9_WX3*1#SbTnDZVt>a03S$k)C2B|`FZA#mD%!a76@X{!2ppR=)N9?~vOspteY?V&i@JP3+Z)T{mlOkz$QF!4w8Zc;pyQ}1Sj55&^llq64U$PQERseefbSnX1(j+ zR;I4Me9)$+XsH7aHt!7GB2JrNytZ5s*1qy$@p{vdBXXeZJpCC7W=_OOw|u>|`9<@2qa!@#o%rw5SeqtII>^RDzRJkeRAq`Ako$ zO6pHpanepqi{C;c!-=pA;s_TVG@;JkX}(4nu_RB~f3Eikbu8sK1gk?1Na5hmWmo@h zJ*y&Z%vth?FabPg&K$rfCVAxd!FiTY@!5SWMi~ez00)V9)ydL{N#70Ryt>y?#^qjn zPY)UNI?llzNt^}D@Qv+d!|R2Z<6bn1PUKmyDnOBY-Qr@J)+@>Ofu?Dp0E||l@ywCL zY8_T5RY*mg+)yy5t^yQKNBYOvD9}>um2$0)0X3Z0?%aE=)mNMOdoPXL1Il{-tRvwRDsa?B3681pCI0dtQE6MSujS_AFijL6$~^qadbFU0nE|rIGqz^U;6I4^o1U{VRhVCwCJKDHK946t4Nb({X|OWSa!6q{_DLlm%Zt=%md59 zLZVMM;3ZMkR3BE?&9=2C5%Bg)`9PDC<^~;4w+J7OZB+wB$_;E+jEI_EzLkHD{g_Rv zG~l1Ie-#l7Ds!Q@N3sEv$11%3FM1mymaC^|NU?tWqtfJO9>MUqnJlZtw5No^qY)gs zPX|Xw&;I<^ym?Sm!OXoBF;j5>FUgsdV3%S=%BgK4`%{$R;M|xLGZrE)yv#g?g%VCI z@)w7g^A79FkmHY2{@8j+(Pt{3pUuXDfu(oDUMk5=z!qnbhxVREN*oHPN-*?niTYx z+^i_G7?PvYV>8X?yr{HYo4;Rn+MKmuYq42l=Kp=&*SC_XX0*FCPI=F^1`HqWp`;`U z{X?@>jNEr@EopJ^q9cEl?^hY03fNn2Lf@b>g~;z?{57I?EGzT#K?ab13zm0;R#rU( zM`Sm!E(?7KW0pdeyqctkox(L7fZBbP!{{7ZPgWoBMCJdF$Pd!TcEMojbbzaIi6|Eu z&APYXc%X%dH^I~7pnX^$tfy#oh;`!bB^MF@rRXvKnl$Jn5gZGWVXU`HZ~UM4*XL!3XQ$0LMjkDZC-zzb%hVS`}$(n zvEa%?Vm_j@sGGRr>m(eAvT^^vQ)3`dBhP0F(ClO3-Fo6Hwj20a_>Np@C{nnWGQB%9 z`1 zdm~#R2b0*t*ltj@WBQ>z!rfZtV^I4gs_f zosxooA$=FKl2s$I9p`k+f#b%dHb-N|` zk#uO3a$Mv2B)WcZ0CGMoSRB>Tbu1tkFb79uA(1#vr%@paGi1wsh9f;S z9eE*zBj8Y$*uzC^?p0cWH4l8(R6wM?XtCi*zs6gYut;V3q&-BZ?v(~vkbPS&4L*(Z4Q8@-g&TA%QA;*^+YTZGfmLMV;_x=;%mDxddg zqx@#z`L1iHna-m{e+ z12WQP`Xpe}HQc~H87A$!*N7q+Vqca(AfJRXkaE_JjN9}Q9lm7i$e}9tvb+Q9z*;DY z*>}~N-e*Qr*QYGq&lnNH{i4Z*%*vEIe-VXA=pq=m2%}D6Ahi2mGz;5{$S4_dLy2So|EP!}wlMsk9RhrNvUV%jmJZbpCl{ zRKzt%{o>16A~H~0Uk1>WxVL~0W+3X@VMU83S{wcNryc;Wktv^=NabKL)Jwv!w~`=k z_OT;-K`d?DyZVh{GV=#C)EY*=bM6Ia(e6)$|8TVx+GUShj244D{#Q|$rn`WZ=qd0# zi2D}%1#7@sX3Y;|i=`bFEJHoHSXS*BEpDM?qI`y-Kcq_CgZ^Y8NXS!Qqvz3*o@Zd( zomXjm)Nx2i@DpL@O{;N&yY5wz0{!tLuvVedG`fdKKOemSHMTm6K5*avhN5KG`~;5C zCaMl0si1jQoBH{x;5!&?*{9FBzan4A~%JN{HD-<0MwcvpVC3BK7y(Q z;+x#6^O~00h`w#qpS<}?Xgd&y4%EyHMi2aW2q+3^Mce0~N8}_QGo|mrI+t+plWW;m z3W-XtE>?0Zgc8$A`{GOoVhGNXL~R)9nN1g9>dZ}I=9bh5`{qF!y=p*hWO=~f20v@y z;9vl_=3Cc{@zjjQi6hXTTKRS|HgXn`&q4a-)~y#SIdrN?nI z4~cVUs`^pnu=S7^8CmOqk8Fn&V5`*|@;>o=??9iAtjYn0^`03?!ruK6f(dpAw(A+Er_XAlmt?(!ma&nq6-(cC+|FW- zu%Wov+~mTiMhiMR#*y>Tp(6|EKW*X)yo1P|pvg{=ek=X*=N)g=P%sz6rQ*L9`&|&k z9^1h$ItK^yaHjX-D8L%YE_Un#X!=akP2I#*h6C6~I)@+}1dv+(SIh&gEB0G!6e-!3 zMqU}I?{HIZ^Y@-a@dF!)`hn;)xSQB_wv75ln_ad-a5tt=&R&m3-$^dTG(elBLMNW~ zuoUXC>8?NIoMKC0C`T|;I!YyFS>#x z5{^J35l{G^j_crmM*qJ!9>M=R9n$MQ!3`;X zniVWiD;vr|0fNE=0}4wd+;D0xt38xGNd_35!3y_I<(I&a$PP%|WWR715<%v{6qJg( z2Z23E6)S;oe*|g_NI*zHozVKW=#(5M)?;74QfKLK|w5tKqk6?V`vSl z%EH@Ke(FJ_#^VO+lsID&rE51&>T04swTtIj1sSE=jv=aq&!$(?taI&l%C(4#4zjW~ zSw2xrG@_b-#5JN$2_^N4f7VVw+Hw^N0rbc(f)Iwr1y&)Aj_p@l7QgHTh4c_IT2}W+ zISK_P8_=M1tG0;re>-A$65x_l_ZNE+_4RajRY1pi-UmoUxK|Q`jY|iKB7o6_X8-_< zex&Uf0AqjOI@!CRWIN=9t)+|^UO;Jf@&Ew9|4%bl>svd#tx6I0$;&d}fbT6Iou9I+ zrek9pZPmvkPcc(R)E?&!W~6BphKgFVGHL$bx$00+vSW%_#^A&yA>90FsU$E_kDdz7 zz5c2l!@dO)(QJsy5f%ZmCLY@i!>GI54|eD>r+qH7(GtTFq2WXwfa0%u0i!gBfB`t^ zXiYvXKqe9H%Yz>~;p!*MYhWDAR0n4YRIxKm0%aa2*0}n6*^4&B1L55Wk#ni8r_Zij`k0DiMEM(g8uAf`LF z^;R^_K(j)sGmJX2FC-nrc!c9oUGl$c8Y6jPl%V^0%hZ%`oTak~NO&>%w@LG7qWFnd z9&dCR9~*}nrEgbsF8J6A5O#kKKi$s+o+($k5e`{{5CdGQuLx7_k@;YlCbES&#j;$F z|5+H8df`+gG{NKon%%gh_n3e$))5&w;9)%i&xyy2wR^tA4`d%-sg3Rd-yM9*1P<9I z;uasKt~IHAMbavpPYC;v{Ch!i_ZR6nMC6*nv)T8-OiDe^U{0|Yi<-G+bM%J5O0+eB} zW(#8NZX?p3o%WyA+R1&J-~A(Ezl{NwBmYrU+Eno(>8Xoq8$!mtguJ81{W@VRLtUVA zYEG%-TiqaUp>|ORtJJWpT#_*G?I|P!+x}MV00ko3;NQw@RfZdSB%X1eRM2DI_VGxs z2b`GqVz&gY!&$W&ThCPVLb6IkjFSzz>md7Z3ztdf740wyiJaWD5AKrA=sBzje6qwN zbLom(N42<&Iu$7Lf6Cu$h?azDL;I@>z+(p_N-<4?pw-6UbY8SLvTu0l&L0SH($ zYg}Bz4t^Ts(17myP)3ie_&AuGW^B)3g4$qFO5xQrx^>@LZO|*X`W2lUHCco;d&WC~ zws|&I+&N<0RgYwOzY4C`A7=XNBTY1tDF6_a?0hDK3i_`0&sBhv9qcR${~|KoqkD-! zp50wHk1?_{Nz1HI@UUh7MF35)JFTdX}P_~}Th0TFujJ-M9 z%QGqpX2HLSo3!7hYp}r*-VyK4S(9M-s?AT(-IFSZLpLr#I){ttMAI?;ZYU@7yJ0o* z33|Gp=*@N0>NGNqNBkxW0NG8nw}7q;HY7*|r*V;ZCDaGB@zSvXJe3YZ)5Em|4`v`^ zed-H-AAZp##XFCxudW*MZBuf5fI|Y+VQ^m{9umprGHQY(e^Ev1(kdq3 zx%iQkhW$ZPGWgEAbxV!Sb{kc~|8c0F!s;g9|E?WM3PXq1>-Hsmm5kG>83oJTG%j3( z`AtLo3y!+}JxqGkCAwv(n$UNQCeAyG>UyZ@1D)clTOefijpxhk3soIsc(ny2dlQlg zy7(9lBpL_5oWpup zB5WqBPC-~=J^8Xsi=R{|AKG?`!wju3bU_!Wf|fZ$?5hTTW!z$p&fjCDHR`&SkNTz8 z<+5s5yI5Q~y}7jE3RjKjCC*mK0tLvJ&xLIksy~FVwlB|+?ApP<9YByCAq&2!DWvf1 zHuW11td@a9$EegF+$uICU+XkhB)oXA%VG0+NO>8SY=A~=Rgb$&%-cQ&sfEJ+I~+@= z)8EH|YGCtTfKBZhXWcP6v%>}UW=g4&>M9#ce$3EVX(cx$E!d}G(0`=p*PWq(hWmBk z@?On|;7CBrU^L^9l6E%~h;g}wvYgU>Wx&TItJ0w<8C-)ny4MPVqQ~(Sq=8^-$*lH_ zB#Ufv;{~vjAoK#s^e3mgqHoQjHv6603^nj;y@Exv&~;Ib9Ysx^@FA`c>R1PyV_7tO?>?kG?qVWoErM~=EsO9)NdGR5t+d~6ipJX^} zo;mIr7JV5TMq{b2@|_zQSmcKRpsa>Wn7gj2>vprpsuQ5?wcql4!*K_P;&KnY^Ae)_ zrE$UHyS)`Kh_PRkUi`bjB+zV$3v?P?&O>?~r@aJzz`}ru^xpj3;!;{FY1!kbE|%n2 z!Scw!2>qRTW?>nT?$rV<6P|aoE#m{Q1pUJf0*+te9H_vQO48zcXyCicRU3mfC9e&1TEWyk9xd0`@Pwg0$0-u<`k79YxBeP0HVgYBL z!jCpkMUEKJ(HIX`6N^&65kg73@p8!<#kP>gtK6W9j(^Ig z!XJ@zgC1wmm|$a-84tigKtK^3{8Xsr!z6r zyj?jjJ-*bG-bt`?1&;+05--yHe$Oj+c^2jzCjaLM1F!8rZt;1N(7CaJT!ExKT})HZ z1Y<8%2BX1N$gu!pukjlmuPn^p7uPD&-1h-MMA0@Qhvd4j`m7v(UvorM*NR zYkhHwTa#N+e+u{6jgESthz+qc`m72$PhEURIqc{(S`!y;Df#vJS;1}?a!c+mc%kr! z7&_LqwAXb3@dQE0XW1ZKydXDl0R5qqi^=|oKxw>P^I`p`WzkH$w}fgVsv~4S3}#pv z1C@kb1#1{?o!RJ77F;}t`3uf zHsi`2j~x8s+V`1f!CbRc9);%8wh977uu~eqaPngtrw;l^+DP!#l=S{#6C)1+tHP3a z(7v0@D6)^Oam{seDs|S1@_1w?@_Nf&uV>fO9F}HZ;6nOC9QMB=S@E^D_2sU?;okSL zrC5zc)Y-bsj4KdFGwh`S7x!rLuQvy{?4I-8C(j5AjFN0w$3qE7qrLUJ#z-|=&kq}( zXJ1!}UU1{ujEuIMlQDNxB}+CYnrlNd*~$TJwN#pcRN@o};wwpPByF*t|3rqWNG97& zm4tr1*KdCSII?Uxn&!Sx_XXfI3a*i+q>{;BcYv6(YAyZSk7pXC&A@#c?g3zp?o11h zw3mtdEhYA~uhQo~VqLqLhtI-KDTHR@wZOq=7!it3_SKLw{V-axqWVI8-216xK-Aub zmcl9-_1f8TiBc1_m|8K#5%pP;ZJ@Pr^{k^DUJ-V$3w`gGGwTxQ{gqtm5>?|Y`#h5n zc#GglF%pzZa69{h=abt#SdpH1O2BXQ#`lZVbl197QQ~vivR+Z$G8gNaiVNbt#D^N( zFRxzM+#|M*LQI6-*C3waC6NCd#9f<%yyx-TxEo=&=6a2ItsZR0s}q!D-haH@yVi~W zEi9LuxZX|z44v_3vEmg*;Q;kha#hjOsPn4%iJX3w?KCDw67<%C9fk(@fbR&8`A7Ok z)uVr%F5)@#xiWt*L%8lQC1B{`;;W#Z;s!V1mL>5^f>F&Bno5T`UC^^c49bKEWY5*% zJ(wmO{b6_>8uW^h1|mIxTmsLA06D)~iWe$N^<uRD2l zcZ7RMD1$7`C;(O(gSwT8^#GBHa?uXWk@u4Hif~x6Njq{SDVIsAC(mel-XS*zVz}ZF8%8LvkQy@`b^RiCie#5dJ4D38NN6R^P=+>(y*|X zx}Wbbn#L8#^Wns>x0Rv|=VJya3VwsDOurPnYCG5Z70Cf&Gf4A&t zytFsLfSvE;q%Fm$?{nCUNw~Kbx2rv7FS<@z5&;seBfF!mZc=rKyLPjT20XE>*=I$Y z8xw-o1H$Np|LybOs*Gv;d-DPJy46$6yri`XpqCsO+)b!xhx$i}&AME256V(OaGufm zkkyUwE0;T_XILUVQI}@NbOM@J$^v*99*DWa*H5Uw@?G&I*N9U$kB#nDguYrmWt-R_ zz7qmTXD}z}u4;~oQpd5uH>JT&zL=QEm-um;$@nc zXiIu-L=}Y^Pzmf=$V{kJ%RsPl0(LuC7*m}4NyPU0F%iYwa3r(h0tU`wH)p1j*NwP3 zGV~hu`MWeODqAQ(zH(cjF-uh?P|WD&L^*{n0rM-i?EdP1@Pfkpu0}6z{u4j543cX= z=NF zI)X+{_CWoQOy+jfB?(`A*{I3oS8b$v4k+Sthsh%j7Os-dnMLgCUs_GY-%`doI1La{ zj!K`RAe%og0Q3Y15#hP^>KpL~k;x0xK=_S3^n@>yx8q+Emoqr3*Nqaf+RjU)dOSjoJq?tr+`7{sWW&1uZ0hL`pwlQVz z^Kb$H4DFY~MRR1${&t>#K^Qy~P)5@dqKLiXd=&ZW^V?kvKnq@i(~Iw;3kx8Gi=z8B z(M5%_#1#w0Ai>Y9fMEEKnd<5}kX*hrQ=6a8gnq*Ov&+>e#7MP#yQM3fPIxEO!IP zLyfNm~$jNdRJ*IkO3^y ziK83x_41%{eZ9`K{vL#9`i%9IpnM&o{?i837VLU3J9ADN67iZbjpa0Ywl?)sNQep z#R**0xWv0+=!?xlsA~|6I9LB}p4M4TQnTo#M`kB){-l0-lctmwu zrh={aE12l>c_LZ%d^Oxzd${DD6o#8s*m*6?Pe#J9zsXZ`?iodvpmPzTwp03KNk0je9&ERrdSV8-ufEk!Sw^Zz9vR210?tymC_Xs+z=mlMDOu^tIX* zrwV@HS3b}O^C1$sb5L1WNoC3h9D_e;fwVlW5)#|a)qA`I*tn0k{S`DD4VdloQrR;+8P5%n@7PK%|ps+=&Lpoj5#fq=hV(E=!Z>kY6f0q%XqA3RbrUkui~)n zl#wJ7c&l(@?08|6&*u-ksZVJ=1$hfwd*{%le2L5p-&D)heG z$tx&Xh31RRGz8-_cs#|ACO|d{-U0=fp=&i?WGFuXh3dYk_Wr)L(*?w!i<4O?+Kc=4 zW`f@Cu*T0Zo41!-=&(vZktAuqGrSd-5I;3RUD(&g9TVU;P+X-8{jih1hdC#`6dfuc zO(%2~Q3-Ox(FA5*arBtcHP?1SfnpOHhN$6~oR&ed|y7KC~}7W{P{H0lqHW&F>7oQdxhHY@?&SG!X@84-O?zw*WYk~on z{slqyM{sax!$^7g)$!R)3s`$4!5cAueYh&1jtu$Jvc&V&mz{9pGLE}YN#zo84@&pY ze3d|tMOiV<0n+n^^jlTbo!TVZM2p~dA(RFe6W(X=H`_ekfsqS%?rKzy*kOp&1h_-B z4s@bxO>pu-)jP*yD$by0oee|uaPy+G+XetfMe9b31M=U~m-FlncK{;DST+l8f;yGKJ-QesXsrcWO_{DpCxJr9tY-uP?& z`e$kZP(x#7bj^}36U}~3cjgq`7wry+U5i*bxa}ai12?>p-t}c@<~A?>xsW-3< zs;0%Yo1W_}K)ex2dbdg_H3cFU8EbwyN2DZTCDABg#haB0o ztLj}$5;6(0;=&|DEztG!Kf}11t&-XYmr@P6ka4)vN4mFrOzZjAgfkkOPA~m`_3O@jj88t-ZD_&jb240rN3~4P_Bo zL^Zn3YwtA}CrbaF-1u;8BHS%g_25saz**8c`vB zVK5js57_8ckLWVIR3PQ;r%C<^A#%~{Z7>g0hhi_xHXV%NsF z8eE%mn`ZZ#t2XAA{g~v5c@1LRftX+&IXBKGg*snc`~l3USK9S|{@l`-p@jZOC~jjr za$7-1X?4B@5|EZD)jk$(GmG`EIy3K&)UeIL44!AdvO0PJgk@5hZw2Q*K= zWTX0G?QOmFkp5FMd>xUMg2Q%~XQP319(zwB|J5KKz3H+t-QcuqoXlJQrq&r|2u7cY zMO)0DIk?;m+q+Oh$zsa>_mG?LQv=o` zj6*v{Cihw?e4IUXm|Q2>EVvoJ-0LIMq$AZa8|H5;al*gGk)n)E?>Wm+{mmue4&#|i z#-XJjEFwMX8Dz1rSfEd2L8T&qOB<-j-e&3Jqp?KR-o@%lp!i$93yR&&FYslX`4Go6 znp}=Yw8l^8@=gvL@QOPX&lrly%pQ8R;gsyCcg^|G{S=4=EZ`beE*Ih1cZ0P6gkl>I z2@-ZaJk6bp<~be53|L!kc6Sk`lX;>m9Yj4%gcn>4<=2IzrYlm(JPB>r-JJss^^K$> z+K(iV=Q`T4-?R0Eu-E4HQL4+QK-x!k?(_*5C6y`1xp2A^l?7BvW!jvku*TL|PAIl6 zlP7DJ(nbjabS;A7jvCsy0vdWSFS4bvGA1zo<@&Vm%Qd%p2_O@-W|Jg%JVd;VYMaj` z>nQ_^*K0R=UNT?|0%k*SUCwe90-vYWOe5+2k1w~lyn*fs&liA@{wsAsfv#m0w*u7X z!oNaEEXq5kL7myrg2%BE>v@{f4|62`sxPD|QZ2*q$WEJUIuy7Z`Wh=a9p$$}0YoTM zbL%7=5-q#5Wr+L1jM?6e!YHYfVwTZQ0>XgxCtEk`o!4N+LGKyCR#c_(8qQa)ywjL2 zG{FkhO6`Pz->j7tvxgK-HtBeOJgHpR8-A=#-Y;U6R|D{jc1qKf(8uqK@^#`CQb>uJ z%DH#qhSjVAZfrCDV_tjq?!vx^^L_y3j^N`odm(nD3j@1JH~(Z)M`xJ-V#B$iu;j4a z;Q-8meklRxfEHk@_CYs9x&4WG6(^Y)&6;)4ig#Pye(E?LOVL?>W`>}i7%i=0$`G+7 zC{u+K#kh@o$5-zSYhz*)fV{(qj}8GqN!ywV4|aTn zlgT(sK%6CNMt+9k-WiPzZUE)z0AGN2cFRS2YyjwfbtF0S2ky7mo?7hV0Nvku4=!f? zaEsXQ9LP{^LZjMjJ?YUyt$)Y-wz47zwBbtI?t&JrvUs@3|?>;Q8R^>C{l1 z;#~eKfY@~k!Je5wZcXKxfn;&2dNvH(bcf^cpOR@Zge>qrwz+gk!og1Y5Rnst%=2v$ zIBO}}Rn6k}Mn_^0@558K6=FHg6@x*K+`wjsF^LegX^3ld7$@uiPXXDEj9^UMEb>1M z3v#pBPYPDfqcJsc2tKiGeNjN7Mkp=yJ*$>ddboAPOEdH<{n~mg+ro&CSN7YL^<%R&B@sdY1j=rimT>uw0Gv#W~1Z5eza<8($I0#*`K#N!F=~uHw z4JUYjNLH|X;gGirVY>sCcl3vn?w}D^ILDLY)uYK46%O4+O6gv;cWdedD8;GyVb5Yf zF!)ko%SN-%9@ASOcIu;p39S96FAKltefuy~-`q+m1f8wN*#Vff?5MKrR&FIY@k4^` zbl3FL8HMtfOxFTLdx%;lA1wbp@xat{4NV2MUx-A0N$_LM#GI}PRPZx}%D{B~`bD?t zsdx2^t@BRSphlUEOk^>Sy0^^v|5_!mw)9d3t;pdO2PCSJFnQ>_@4xOK74#8xO2^HW zv{RoFtPAYJ*3O;KOa;_W`V-E^$N^2b+h)7E<$(h*W1aJE$`MX8_o0$U=`{-^cRg|R zhlzf8n51a$jXtpTEJWL*wxoIS3SUj=|@%#D)Sau z{fEExKCKv`CdJ>c@_Q)AUX>OEQ4}7~c=pCf^#vQD*uRg-m~)r>KbA*#glYgsSgm8Z z5b3VUjic)ZxD~+NAnh0g0>N;K{T<(&vhf>0A9yVPh_ermwO_BAI2JIBxfS>6I9*Nl z-U1DN40rj+OAIF)jEG22;ex6~4!j(5&>|}9iZfX6%eJq5wwc1Dj&!mXAEgU!gQ~T4 zVEE9*Z|KPhIlxNc-Xafvyglb|(*JYcDEQ9+A{4?BS-|@*|C0^ZLIL;L5~^}uEp67w zf^i8RjL$PU*=C@p)kS92kk`tK%a(6JsodD-C54dx0SE}%w&V9?MhJvQ?{J|9!hC4s zH4L*y;7Nam>a%`nyF6DlkRjaK7G)zF4dJ)*>0Ul#_DG>B<7zA_OSbel)vq1|_MF36 zo0`U!#TY6@s&t+aQ$=mDE&_<9%y+i(i)n?Mt>DtzR|gn6X&YobKzx064RQa0Q%e)W z(2s(|DAaydc2MCzZcN1N@K;!z@PgJ4i6N$nrnRqvUr+nkt0+!plx->Zo!I&N;Vmrp zXLekv>bQk>ZVDn_eZ^94G_0|Q8_LI(g1OPU_(O9rMO(Wc05=Ful^4Q+NX>qod?wb* zpA^r}@Hr4oBm$F&PC!spmw3lGT6|6Nv{}{dU%qaDFVvcAq;lKP|TOhzrZWU_**`0By=Xf zTT4=g8So}@oqNLz1^Ay!S+CUkGcnvCFa^zqT)!$$R#@1SWCf)Yf&6dv^`0@P zkT1*0q8vhFv2XPjr=ZKHTLS-0r3!h}K8>9glZp}gS^m}058bcO$>8A9l)N;(6qm;3 z-v_G4gb4R#b6EqHr}Dmox=UW=4biBnRZyZ9y*gVld0<=_J=EsU$Vku>J|x<4H@~MoqB~6g zW2NhOr{|V~SC`OPX`M1O;yp;ZCe~9e-#yVioYRovfm%-5#F!~3Zt`5<2&WO@tSWFh82TL}a1yG2-uNv~ z*&&L|wOoX5L2TgKp2%S78op@32{N7~aLG_XLTqZhIkqW{q{hN%5T`QwFX|oz%Mr8L zI-5hcuS$WB;$hkEN1$z=mz`Ivkh+^jn{MUlE3|d?{2Z4CMjH|52EhpB>HD7|dknv7LIUE(#ucZqz?O2e*XruHk6GbKLe^-Y>Qtd$HvI2$?Nr}Gj8=I3I~>_D@_yNt1EA~r3nSC@9z zOx|JGO?E{HrqkQI2sVCRNI&;+BIxTecq<@zuhpDyR`^`>D7z72DI(XSdqmQew?Zx{ zq>>zyY7o1Y!2uGQOjg#c2ue$9=>Vo5yN)t^YB5n})o&@GbM7LDw-1{Tb!XiVQ$$8Ht>4X$6)VK7XBHvj=X z;gMX{7pua$NkzLvH5UV*Ic-Pb44wK=O}{O~Vi3r1m@B9U^kE>OTub-QKFzA>69DlQ z#(V3eG=fHAA0nx`WI9IlC2S2>+j>sx#W%)=5w`5+2}U9zDh3FT)@wIC8ex5ktEmMc zkXjb4oH&L_hEjyxP&D(~%q1rpT%#DxIkaVmFgXYBgjEGFolY8yq_7+@FV zS^90>83E0WQ-bJ)mv_G>)%uX%!87xal%e>we30`(5V)m(mtDx4KhtN?Djaw*fPR^& zVsg?so~qTU^~V>R?^NlShJtXIv)jI#ujp$*->!R8^z+oJb%T0m%3u}R<^WUs)GT+`*CO<=Z^jOqTAG?Fqv)!N)OmLpDDw}EWb3+zr;p$^YF;gX ze)?HT;Khd?&3(#?9v2cVqMO@R+%nl^izb*}GgJJID5^PPPdyF{a02nfKkFLr!rn>c zEmQWgOrKpL53Zv2#PLLOING|@k*RBswOX;EZp)y(AuDuD!(Lt^GI^?XX?NMHZT>^o~SE@bhqM|jRL(EQ6@ z5)Cm+F9x#w`wTPsh+FyR6uvcxH+Z1xBf&M%*~pylGH$n{7(y>9kjo(ds{K)^9LwS> zWmX)}_m8$p~~`j+F@OpPJrW9$-gJMy+_{5IltijqiJ^-@RtE!Chrh>xA_`){7PYGGGD!s+3+m!>^ok_MQypLpLKhBm)VF*#B&YRKss zt9aQmH>53GfnB25nqc@k24UUFmX8%m)0nkbbD^~>EtC}K0vB?29GUnU{oWttx-*ta(TF8Uz+Zo{f$ zD|NL1_iP_BY`T&QKkG+w2(T9Zmb+S%`aHv>BBNfcAm;NUb7qt~&g_r;l0=w-P{LK$5jLD(Jq-5sl`Qn9ZXW=RQ4)3XP;qTKwg-}f{KmlbOZd^aMK1#1ev%hQei-FdsBZWif6P8ppQGIcg`>Gc{>yrA>FTR|?`d+VLKC@D2goE|`iLD`UT%D>ZA(r{^fG~|@unQSim zSU3yF+Z}Dqz9iesrM&GWJFg$2h+C4LQuHXdxGv1`l^w|Gr2xnuh;#VL3blnFzUjmZ zyYpV9EI&8lGTjcN(4A@2{>$2fP92V2rj9`kG|yv{INe{A0fXBDR@!FW1gdZAMg2&u zPCG*}oRS0nEam@;t#=3(h6%bfuWj45ZQHhO+qP}nwvG4Nwr%wnJ^#eSbo44KGHX|> ziah5$c{vvm-s;TgKZ!7sr5F4~x#_oSZ*4En8QlcS>E}Z#1({SegNH=Lp^j!f?N6pR?{*+h$O)F zOv$BqtJpw1Z{#)&=tac&kDy9!gwA7dT_% zuWT&O&W1=s(1-HfWdO^UI^kz{i5U*l2SoCWGvtgm0TlFV4u5|=)}e0zRGY3?Am=vrX#y@D@$-%G zfgdbgz)6`QePoWikAdF<^Npf9kIM$cvAx#Kc0&agoYp3F!SUg&BUsmA~h16#x-5c{u-}rWzS`4dfC3PCqOTN85G*g@XI1^Tk}$VHAMBmX!L_B#E=DpHAJ?@{jgNe-$o_av5w=&Ft-qz0H6- zXruH)B(kg&WlWR?$JZ$QCdBMw^}{b|rjXRRmX?;HO<#M@LDwoUs{})dB|FiSI=Tc1nx652^SPK8SUrNi+A`A;rC=3`l z)LOSMTsoOl>kt|s@sZ?*yC1c3GKqnL%`S${6d%1MPtd?H3DOXm2KCnH2DnP@&}b-{ zL^8EPmnb2dfWR`^4G%`_%anMLA+X^vZd(Ixt4wzh zz(hyWy(F70qEy~SCy{_cTs`XC-CSbti#Lz09N;<;i%_6a zxvKrshPOon|_YYRU(!gI!l_dpAx)gT+`%->7 z2rP7|fR7kNgGT)sZMMr7WXTL>=9FaBneTBG$^)9>hDt zn7iY3*T*TT1VN=N8Hev9b_RMm&Kgu^zsM02*1#tE8#R(oSB7%wrd@#xrRuNbfpJM> zHftETi!Kzeidr`;Rr< zp)iBO&{?od)V?wcGW$RWsak?`E@?&k&$dcg5MNWcAdaR;&%7cz-1?od!QGq16KSg; z!2wjZOtT7esJ~OsQhP*QX^VhMdC*u9J493M;&AGqxr!+Z+okg+%QZKhNIPhp%sgmT zh=$v|-%-3n=^umNohdjmG*w)|u6o`0vc-iM^6m36Z^3R6ZQ#7LX(dwH(c1FV;(s#t z`tyz@TVo-?BAfTlzqFu$op-+8|44)K*&b&mh|z#SF=V*_r$lJzQuGzj!1sTd6u{a1 z2uU`$Wk78G64(tGRQ(cVw@-*B2}JC>;L_PWE0EG4CW-$@3TThs^~!Cf|(KE7bL~Y?RNT;DFE|Upx#_AVmlUmK#I!%{w?7;!jsA&{|l!*#&32d zcxcn2UY(9=i=50K<%L`fN~DGz9)x7x1t59@0PqGP?Z5%l|6S(*9w?Ilv)@jJEj@6} z5Y)=s7YX?PoJ-)cv_12wUxO}WDwY3FsS^5sPyf^SpW@@5*f*qX(>NOIB*oDIn+~UaI#h-cb@(~Df~lxe z`kD`>7S|LFC;L21m0PM%l3?^R5}Mbwz6m}X@N}Cjp+J}&L*x2{vHjKF7e`SW*`>Yz zrMJv$+~YX|w{ab^;h4A!oWTtD6l+(E6%JaOq`P-R3AHKNutYCd%_hmyNP89uDs}0S zJmH|3HQCZuj9+4eN;1?+!|&4Pnp%gEBSX@ZJR;)Vq2@tB5DzAm6VBLHO6z>2m_29hHV7q%5{4V`sg z^x8Gt@`Jp#`CfW%K4%Z19w}ynMg0=e2i6LiV4l=oeUI3`0S_(R8mvoi6jY-c6fqLo zwCsi?53a}Zm}`G&J)+mv&&t*?$XU`v>;6W0Ywr|KK(Q}cG2Yj|HoB12$x1B{qFH?Z;HbS4g0#}Hcm)^cmj9b6r{4r zV`-BWe!i-;MFHf?j?mIu$rhW-Y8?w^VOr>m@KtzvO-Zi77Lqodu+@|`g_4obAlRER~-CfgL z4WyQ~*s15;{}Y-r0T!j+KU>zQR{t8@Uzest{{+iGs2x%^pHnq|$N(=dHHBLZ*i8ud zGvl>Z=pKkr{_0Jq0!y13;Cup}<5LVa)m~>l5Dd*RCs%=JHFYbLq9&~<{D47{spYRa zZK%jOKEXh@b|}fbVMh*kS%o0q$M>U8DA=@KvAi#V69H)U2ZkV(0Euy?De}2J+k*a2^u!VqMI=cY4 zktVnTr>gtaUsX^S;i>YLFVFc9#S9(7YSkO5r&=Ntq-UEGw6(~h&NFFGC4@QK8d8%3 z@~O zDJbgLC2*KF0|NTpk#n!Ak;;2WGwJg9vlv8A_6xy{0VByFmE2>l_7S+3FY3DI9_Crl zwMQuY<#H=^17Nu{o4w(Y=&?3oJDj9IAr=3LEwK9OmRj_lO+_Y-kh41GD~JFeHEIp* z1A;E5b68&gJQ-q{9E}lFxm7blu~T5-l*gCeo#?bbJN(giKH99ezF}L!bZ-v*Of=mf z;6Y~J@D>y~R6#Ifd~mZ0@_6Fh7!3GQifhxow@G zMumDrTA*jjH?D-*uT1NHj!*Jtm(#?YO|bmbrd22ihhB}%q~(9fXK$O6MpcQTlClTn z1O=R#9=Z3S1R7_R(`-mnHsV2NgjL73WBq|8tOuopJ!q2eScEU9FwHvfs_FK_=-dQ=g--U6y6EaqYBauxVb))M4q1lwOunO*$_wKV5k=`hkJQ5}NZK2Zw;IMi97 z32Hntc@!Y9y(~I{U&Wq!>OvtpC%;76rdJqst9?8R!5=C>qAM?P;Q(+~+1_+qs(I?(j2* zju>@lC)fkL{%c^GMTN^QV}F_A6cl+g-}7wGq)|SLDW{SmSJ#BaoX>0frKpi%fJRq$ zL3Gl)Kbz4izp&y=Axp}ZdjI~E-@KO8Mf5>qj)|+%v%5oka7CvPT8I_KPSOcHI%VGf zi%CcP3(Htsu8Wf3*M^cA!qlVbYKCbkt#_zSu_~r%X81?ou~VzRZyOX9);@!7uyp=$ zjwDALDY&Av!5KZgjyuiw({6jd6$@2~JtN_6mnIyoel!)1a=ZJPrtE`2U9NPxNc6dP zYwKu2Lv@5`>UjvJPUX>3oYmZLd8poWz>AvU^Z?^HZoW8#n7#yQQ&XBmoAlM)j5R@L zwYGbC@A{?<_u4hWwi%Zu3B&bi>u#D^^0nANN|0H|)Ze0XAWmIb+|^T=GnA)_xGMn? zPt47kWcacLjgFh@rs3wGWgC-5hnoY}K+{{rYxk4%06)37gadx%z;j$Q$DP{6&oh{t*IoxAwRom>d zW{5x>tS_~W|FgV={yD<%u~7w#Moo2C7pz7T^59zq>c*%8JU>wL?2!p6oImM2UabR2 z^D#4@KPkyzAU?#UB8I^xy?HTa&Bi1E(j> zZhAx2^eWuL_g9Jh7ZsEm^fZkP;p=2eNKIr{=ReS%vY{~JE&2pCGhZ<;5XDG@O~K*m zb7{HcHIc_uu%X(b7{sdjV@>nBfmQyZ@k~HlKbe>Rg8z+|m4&uR)Nz$;X4t^Hbzic) zY#tP&79}9Yl~3#YI_%t$-=QtCwr#E-t3ybM6RPdLvS=G zQW=~VS$hdI-V^#LkTKuq!*XDCk=<3`=mM%Uoofzf5^T|Cm2MY=z*6_d5IG?MM{E>RVS@olEt{!W5|gRN z02wXR(SK%Kv0l$VrCNX8s2p7NOpGJX0?xvEH&z_6So!VO?DY-?6`bnkqZ^P&mXY5+ zA#oF9H87vCH{Y}s+p-lcI#E~8b~(VTTU~`SBJ39W?r)yM{lc9}3;S%#&5lym-)_2G z@=NaTrK=gg$bEM?WxDS9wU38fs#_DY?6v z?Qih|V@0;?CM7YcM;7u|L}>-6-&=SOr>^Qh{|VX>GdhpHSg`oa8o^fMQW`6>$(;CE zI1h*6=^9{5c3slTh8d(fA2Bf8R0vY?`j!ktFL493u8tK4V;|{SZMW~$qJntdNQngU zoFKgDuBB?Zv_OZRx~f%Iwb}}7KhwP|hl$Ys2nVJXEb_t#dCxQ*zhv*{9S&$S(wVjm z4mV6dc7a9RTB(S$x(x@gKzEEkoAJ=36FC;dMNMdTP?spq7NyaF0GGq-%$BI!S)4C! zApz?c!Zn2)OXu^-Y+iU7>}`;r>RuXhWI`u^9>z$DeI^`!J}?Av$$h z@Mr(lSDj?y4n0W2DrUHT3vry~XX0lS`A^%W2-n#F6%(Jty%NG2?+v90$J4O@K9{mT zsz^qWv^80mNkSp9m(Qh!Ia}F}yZ-fysBga8$ix_f{$(Gtrrqh5Ot_RX8@G?L`-(7K zPPi?y;I02A3;j-KJ24#KkTp(BBYPwqf zYm4SxzVC)8c<{ATti%O`_U3pf(~=m7Hto>DP3WN{u}??=N}($sh8WO9X8(S=Ym|;o5+FsSteppKo6&T%V)xOb zjA@=J@ALN^?V|ss5O&E)s1dJk56dcEuVdfsD`M-r$bBDaB75E;fJ35)loUuTp)>}w zhC%l)jq+!V3nQd>zFz0>E-Z?U7z%>zUhCAmbat-Q;2>T7#8uCLous->2mvQ~`I{UY zoTPOqR&jsQBhLtvum)JU7BZYKz_C%jp$gC0t3vLZS%0Zf@b6-DjZ{9b+;aNzA+J9p zdD`7dSk;e{&?5s)w5N{4+-ZTg3VG{?7w3!*khx(AQnok`B)Ta^C!W$9QfQn`_!xFJ zU<>{!kRy-!n#V287Se}jm;t77|IQ6(4b)lpts4>31gv&9d{)0GnfFT_!`_bGgwwPH z*&8-qzW0^vZkT+fyVB2vH3>%ykm~V;BKbsnEMgvwl{s#> ztkkkdYm%jYVGFCH%zP)SCRmh|i}+(ixjei5qgqf%#<{7RvfE z0hD`tI23oi^ICOp5-2MI`6&v9%h;T{3$}n|J9mYM0O%HdZ?6^DpKpJh27`#z%$xP5 zf$$^U5fAb(aU7M>Qq5Em2_9`AJ?&k4m##=EG23QQ)z<^!K}B;Gumn-0wfHYD$rn4v zJ;~&S2!MdCQNvEWAO8R_YYTfWxKz=G!gQU1b(PY|)u=K38W$zgO_Q2v!F=~QI;(Z0 zNuMXD)_bg)fJUAaJxNTVc?MHiFMEHHLq}CWbt4aty8oo&tLuJ6&jjNT!5FWb$xXD-yx2m6@;J$qmc zD7>{uifcrxBCAsw+yEZOBEG|fJpnRoqjlexO-lkXX9;?*U9C=-Q{26UHaEddQ^4xY z_QI&kI4#l~bT1bwn-pCtu}{*+6&DG|94DA|#SOGSq7O5Fb2k%wjBq<`9ntUO<8+l5 z!xN~v{LnQAf>R|;WEqsMr$gR8Q51_iZzt5231(b@{^sPgwIx04j#IirBcPb~LK6x3 zv)%wM#HDHh^J&VPF3YD>EbfssPTtdyeYyKLM|C(dkx+u~5DS4~OR$Fa(M8xh!X+-Z z!l`KUoaE8h>i;SD9z`5$8@LZs!FK^-x1L{8Y5%ML2APs#UxpTUoBSd8CMTA1E=Lf? zBKIARdillNj7dpLakq0scQ0_szxcSgi_L0{w>f(XviwlY6a$KP)E&y725ro)WBYgR ze(bTzQ@10fi{{8KF0Y`x#t~%>&;8CXTgF<%j$AD4>Aab_UPc9pfS}TfAp@)GRX2m> zBakd0M>k{uBHO6RRCT@0>9@8%n5bn|_jZH$uLy zp7Eg#q(eHV^Bw5=;uG)~Zx};!`{SNTMoRJo4z!+2p_GvccW$a!v0{Yc4DRql9y4zW zI@5i0(7}l2PuI#vuC6otbmORJe=%z(qnf1s8B_f*h$v!Q_vZD*PODyH$~&gSGb6loz=`3lC3MexwT&+TG*GrP~O_!%LZh$ z)ZfQ;l_Tp|*aQEf?kx(R-f&x4-@&TMz+5c)8gvMkfkUJD7Kurc14tt6#!9CmN9fXDD^@PNoR*5P5Qq!UriEZ2ch znlhy&5V>^4EW{;-FCpk#lfI>$uxRf zV7gxmHpndR5kJaCui_^JUI~9v+$7_Rh#PF=f!q%F4mIuhPh?)FTm&J%nMJMQPuQcpcASp!fq`x(pY@kt&1r}FDx!(n_!H=O4saX zac5YnwMdN7;c96i`|6SW150D_0uL+RJZil(ZuJtK1@|`($&3snAA-ABz@GjKJa%vG zN~@vbU=K-6*wq8GHyUiUdx-p5_lt{s=Ov$+S+mWS+{j6)jDyCe{b#4$D>U zA_mA5y)N>=V%DZ6Et~tNjx{5F$(ytW_TI2V>g25)2|u6w?EaY9FD(jk=SYSR!re8= z2(=sAbY9a?hQY@-Y_gnHfxTYvBv*uRfgc$9AbK8|?_We6qKj3A_Er8CA#9BzIO>8p zYuak-kIy)2yXeqbm&_Lz0~JL|Qo!_|aD%F3`q6il-(|)eWK*_X5`&<3_YN)r(}>pD z;;YCms*Z8bHBUKxgLTMu~bTS^&u}hbZ-ZQ2|Yd=|_Ikg6iKSW?4G}15y)^{muGMW7L{!yfv?K zEO86dJ!8kZI?G~lQe{i$8#eI#s^g)VV_40mDC4pily;PjV9gJ9YSg4x37@XvI0%z9 zDnE5QPTBW7I2v$pI3?Spd zM6O-Byw$R-mJzJ~aYowM!NPLT(fFvj&b_{fJ*p z^k=!#u$CVtzRF)Mq36bCH(Bd$xd{%So95MToG2i!)cl@NsSUM;ubB2{t`WbLf&=q5 z@Wdv~$_3_OhsU00dGgG;w^;UO(>SINISkZ27Q(p`=sKpUINN1wQ5UShew4&}4H z($~UJfDW3vMAN17_jV{+Ngpkl@MS4H#1h2tvA2zcuFkA%y3<%>f9AK9oe6%kjsUCV zw|tFX*{xFU2#I<;JtZAwXJCF2KfOY%f~(whNb_XlW!+O}7W&*aj`+OhL1Viw-d!b> zmR8I{Mq)HYctv;@lQ`LTW%pI5Z~-M-jb@yoZoIdTC60|{fYP_opgVh|IR4jM@;e^60>Do|2P+K{|#ceig2S4H{B^z#NA@{GBAPYDr0F`FC5UwI7{ zd{&Sf4LP{LB01GDxpX3iJ}wyGnsPBgndii{8aDyUgHStMvvKgfbmlD+wcqfe{9H>P zentNpslgF>-u4cSXNp!AZ6xh;3ncrlf9|v;?hWFWyijEa3P2V}j5T5aG3I(Kf%eWa zO+VC0TcpS=iiX?1tFuf8kOYTnA#P4cRRzqA#zLWn4D+rmgDu5#rfAD;8mgd2Sv(u8@ETP3OkLbDi*=-@m%N zm{X*I{PwpY8^bf#UB^F!m~kLQY>uX0>2kzLHS2c3)0hB>qbZFH4ayJKzV(YrhE| z0w*to<0_nDTJ`O zI+svBtw9kq``g6p0wURJV*XBkIl2b!4YlP4y}(nb>G#9tc;;@K3k<624&k7FmeUuh zrsgp|eSwpWwOZ{J+l^s?yW{%Tpix_U0xj{TCQ>GR8#F^ocC%FdLUAkw_raw*En3Uh zU|nkd)idEs0vYQ}WZ|*swDPnqLT|QOMgBZcF5HVp$!XnSTpVG2UI@=k%YKraxqvG1 zx=K#=<+Ac7skUV5xmd(89}uhiKrCwV9D2|s^vRW!3s=4B)j@LnTgNvVb9z)aBSs=j zS;<#GX#kLsHuFi!gZnRkOG)B{mD(yE1RarI8&t^cVkaxhhsM;$$HU^9nsUjK!3>G- zx%t&6P(U&-L;H6gVo&F12}HwE`?#!BF${e++VG)Znd5pN`Uu9Aq-om_xKCCh4FJ;W zeN?({^YB^y>Qt6TF2qhX+|?UHq8-r8;T6>)TF25wQ-K;2wSMAX-yu0$j_@^Bg}kiOrJmqe*#EM~%jl z0|LgVxa4|hW5cifPIx-VIEH=;8$@)!JMp*)ez%XV3K(y}p&)1?ypI{Lk3f(KCNK6A zbNfM{``Ldx2Om--J$$}ku%1SV(L2h4B`saTcbhYl3-T$?mXGkb7kFdedM7$f3QtPi zWf_OB$AVJm_^PZ?82`RFqq>gE(manAz-qba@#%Se}n4*cVZw)sxzXrML zBXb{qjD1rQkIWRnvMQ}>qU20r*bE1JcLap%tCy(h{gwDo+!QdfN5~8C?+zmkChK6*WR{*8j;A_?DlAMfrB8AJo%aCj}EceGuWd40jCEAH=%9NFs zheA0+qv%>1O0Uj?b-o2N3`GF6%zUAXt>GH5l=|g>FiV z&!Ri0AputOB7(wQS~z=QJ~VSPb~IjFSiZfW!u_M)N`Rqji)NaL@m)27ED3D@qr=Ue zqvWB417}Z)rS{jw@%x9XhvB{I)InUuWe%yud-T_#)73MEVKMaC@hbl_(P{mjV1S6q ztI>612UZAf4A8?gI9EQ;S1R3{7S;seZ8-vO32kMKBIhh`BB}U%*JkiLj>-%CpdMMG zD?g(s(ONCk&eNKt?^e>IsH+m^DSfvb{jDSC5!B#jh{&}zILh7@3&Rh-#E*H88_kwk z?pb($+)VC}#(O0mrhqmtNKSCXzo1^{L(W3k82Jt-v*xS8%?#uhmnS*z9;8(EPp^>F z4T#*r-Ta<`j5@=`wNFZa2ktXRk@qvYPb)t3>>!(x(uqe%1qsS9V z8WcgeeH=HBdYJoDKZrdqFxI7SpEXVjYIKO)6H(lJN|}P5eUXSDXhB_ktbkGETW^7G z?v8AZKKgdS>1=j29cp24oIc+5<@^GVU4Rw;^WqToRaUDk$@T2Kl3t*}e6=UbcGC^e z-KWG5d7sHCfWP&gN3W|)EBQPoA5Zizi58ig1Fk}V?l&uct~pZ%b)vDt@mhC0gALnh z-O#Glf15`-eni5==WqIX=v;l>8T_tj(iKLemJz&S!_1npI;w|&vpDt61g8GGe^q(m z8*dOeQhx=ci}Sl&HBU4?bLef7wr> zn7wo~%F2sKCWo42&gg_Hhk=CLyW^)BS;@%e2@IE|4dlqhRlwJbEMSwLl>G$qY(573)>WLq(mPBTqG-n(f`8R`b($dP{RYe8P`RVT^QU-i zV0(-y^uGa1O$P?aNrQGq3+IVK)Rp|~pe*JKaoU^d!|%=sB_(^q`FSP7;0j}a{Cz*Z z`+2PW3qP!vlxh~>&_nBS_@HAwVt}LN2c#T2>o?l)&m6gD9PHvWmompzEADi!4Fm8K z#9hq3xqhg)8PQBEpII1&FFVhoZgL2gUD~nQrFqz_^zIY(DtMkxGNsAS; z(Ogm%xu_;cM=o6IXF>N@p(^QDVgjO~#kl8|=aMayCxC;Em^`56Noss?+hqsR$pN(ad?zXPv~nJ|is+oB`ZCECA2yc8ofSw^|KI>yf5h<5(K&9(PIH z&zqNbY!=z0Lv9;lUhbo+;(pgoft_%np$Uq_B=o{2ED4{#wwACr&VNm&9}cak*ID6kLjaWtcp7wq?GGPYJ<-&^xqyu(B1R>)4h|FR)VSRdq7AYmQr zU+96tE)K3I}bMFS8f8M4Jdv%5@%uH&{mu#B?*BI;6KDhc*cvMr7~ zm%8hs)P|K=*Mp#yx2O+*RTr*Lj5 z8>wj#aK;cCZTO{|9W}mm#I4UB+u3=<^bjs1e~_uPpeK2sT$Vkmugnrj=0`+| zhg<*23^lqP9hYbUH3$;D%6i3XaXHwdZ&qX19YE!5Au@^qMY}VS6k&rbHLOiaa87ar zYND*(cF~A`X&njsvcfZ^j(7R0phS@gI#epuyVHitpEKbrm1;g&plaf04&fCGH+G>_z6_NG z#E^Hy>=nw{XlW4Tr*y?HyhfRrM*jquR@&%>-8DpHjQccbh>ZM7S{@+(bhF9GOd_-N zCb)6{i5WRW1pyp9H;L@SR$H_#bxamMQ#oh4rjz0$TyHKZ)vw(|eMRbUH=Wvv`<#yA zFW$L6et|nR-m$h)!%JF>@BI>N`%N>;n;H=9dVi=H3U* zAct&0hoq-iMvbc2zIA0QoJ!sX%QNE8v9^V$;={wmDUR8lE1|QGv%8e!2FS4B~+%g8hR5i!iIG0 zhS6H?)Zd|QDC@l02lpmN#C10!G*G@MR^lq6%)8$;EE>DYgc@6@6=L@I4A}~_9BM!`aoj16G zfqlVchqai7yfa~R13+kz)D^e+tJ8~x)c!TB6#c}U@8sc%jrg{^--A)~QFm~1myt;( z2EA;)azQfl)0J>|!7h6DpxQqPBf@=9-}0M0WaAg#>@Ae`{I4SYT2hu-6k{fkgQg5R z6c;OTHe!%niv0^_uzwYmZ8IOtG+NF7dbJrRO>e;4*NMu7KLE(x?M@%3m7x<|of2zw zmRaUbFll4vhE|&uSos?ZNV|?7j2eD)q?6#UnAoq@mU6I;J!cL;YKI+f3lu9oj=6~n zE5VL$^g=7WulhXW%`f~O4oKPta9S8tCve?MgH{@h=vPC_sZBR;bYXl!zDoYvBy`oL z!ab^CfPu!b(mG47oWM{bKz17BYJfPKEmITWbs*zm(!%|6#K z`09#;4yeIc(B}Y1+ATQA$|Y-nAn+puPhdzakkrt=5Y`~gh0SWO)pW9BreM~0p~V=r zm6X23ULPYk=j-6Dr)J{&-CSHp6G0(WTq9AGGN%zAY<9xacLi|ZJqB^ks>6NU-0BmX5=qSQ5Bz46f1zB5FN;PW{9KO{Bu?7h8w1Ni>B~uuE9N$=MQtifXBA> zFrQg&V|KrDEoO9e3RjD%5y$@MF}?`z3rI`#Thy#OsrjuLt6N~H=m#|5G~PLy#O?LY z>ZJvZUw%P|LNsS+1Jdo>H-nJOFl?@{Ed_pvVK!s;azjy7X$CEX3R*dkLV7rY)Zcx!wYc72FMbBc5f(z zqRK*)iP>=+v#>=K`k3E%nzUKr=IM{hAoMOJl&F$&vzE!WRhuE5F{C#sXE8TbEB8Oc zWR^}MF}K=7sw#+Yu}@xg4;A0iXvMoGnr-Q6Ov_+(!@A%EQBz%I2k`wW)4YQvrsss) zJ?2LS%;&B|(n$tAZte?0M5zY4TDf55{2asSN$vUBg&f>j0?m4NlGI1GQQJi1Rsq9O zn8%})YQVgrKzr*+w7oJ4T*ZevJiFYkq$ZTPB(#30A5FL-cY%Rsu|d~8RJPjEb-1~m zr|i2bZ*d3Io;hD^leCH$qGWSa7s6eU2r@8OVOdza7wNo3&(GXV+qlPlWS_~=`C|zh zDj<|Ld>Q|V=wFqJ5(k#dCC@s9fV_>xYu;5Y!CM|~6P2N8KxxQlA$=`r@Fs~ny}qAj zf5B>cts@2Lj$NZ%F?DWeWS}jVUtE8iY0Yv8!Z@htSF;pLEQ$h{nrf zURh7l;P-#`&*K|qjHZRXUG2oe#5S|hGN_GqsyJV6Lq;qy+CLOH$0kSFj#~AGj8M8% z4pw>bAYQ*J^-=LYqJRg|I!y+N2yIgFsCc_PHKdSxUOSUzR^KMxr5cA-~*YRepN2fo1R|M5R=nUv(3~o~a zVc}zI?9&HcQz*6MQXcWT_wT!SHQXJvvJ)$S!fWHCDZr~CwhA9s7+g$`7UD+Y*yxAx zIF*s+qWi#2-#g`&9{qC{>GPu36|9Hz2)?J4;4<~mU1LxNGQ1I3519AGXYUSwnrx4$ z=ZyU*>&aW#lWJXo2D*MXxao zFu-e8XB7(0>GaEez&M73a#EVg^1KcX+5(U^@xg1&*KhjX$O`;@Y)$qOOCoXN;IPS8 zI`ozz*`v_bOW)vOxRsB1=6Z;_Xi$irSs;ST_;{Mb_2slYEInTf$b<<$KEDZFG&xI{ z>aL!6A1U(l=kQbE6YqYg^VZ`S=Urv181y)TYB%E?il-R_ylTO6mXoxD)| z{>=eNR&}bqmqv}{?gkIkVJ`-wgH#nz7vN=SBBW<#BG;RuvaRi!u%Pw9f(>O=k5AV}qi!WuL z>{}`KtAZztl`UFb@DkpPEdG+o`Z7J$q$=Xz1$~`ssM+}E^Z;&8{3W!Kyt4=y0*1}R z6p7R-DE7rGYL-Fm%AYMjl^HZSEf>fPbzytdZbZS;RKt}P^&$Z`6%H#fyiCgk6hSP2ra z8Wo@yfTuvZl}#xzcT38qQI()cplnm>l|3gie*x~`dntFhZ+6u&)-GLIFd&X4j{g+l z^RdYnr9sljKxlWvxmo))8}uBg)&dz`4RZZ zn*lRI!k%z@h)gUtR9G0!#+7V0nK+{ZL%XX&`xK$UCc3HA%eD#38VGUDR~}{fSc)~3 zpMnmp5_Ib%joo@Ms@L!s?=gCrNk4aWiTVn=?sRH{{LL5&(Ead8%1+wbCNWIVLEu=| zMr#DJkfCNpjfu;)JZW()@=i;_j%eh?%ck3s61o1>O9WDyN0SJy_Yaa&zr2R7&cOS7 zLSq_D*Jn5pk*+*u;K;+FuyVn(ToE|H{Yoz^<~CqKmmYr_=wwT#{u{+5cSz;fP^73* zKLKev=1N=e+4?Y9qv{G<5r%@?*0>e};BFPw0}Mxj zZ-J9SR2#&KMg*Q3-n-OOV&(j zH&P#C=kx3lpefjoKcy0HB;xeE>=;W)TgC;1(OHg+CO21&TJH=zqLE+uSajaho6Ck7 zJC_ec5{cGu*8C!K12q>{N(oSArMnu3(#`I26 zS!?txop287V@bTpjW`83P7={$W3)zbv9lRD&VOPYGg%<)y;!sE0@h&)-wuKN^ty`5 ziKapJ=u2a{6)NIB3c0VGOsN^0oRq)OT_w$ZhDXw2BJ@W$`se=8_&8Q)qYXZJS*yr- zV<73hVQzr{2`j2=t}MUWvN>or9}m~u8i`EZh)2x;p^JK&uu3LY!S}tW3y4!)MvgA)V2Rn^o6k}DAMN#Gs-3t5= zi&|;Rol3DB^O+XbtG%?F&1ooE5CqgV1~*7J%=2ND@qSchzI76=1y?uH$d>f+MKY=& z1qUWgE*pPZd^)f)&>$ldJ5(!z|9=hD2L5#Iu zxZ#rYhvu8;YA*cf)N9ck9hvlUyJ#X3>|K2muGQR_`cQA*05|{(9B0H|?qLXcp3!b3 zHgj6S#L2vVC}6g=-yzot&Z|GVjQ)!u=HXkw2<;HUGXdzis+1NXC!CO^9k>kpn z?%njPhDevF6r9;i9WKC0XyaUCw!x*nG+nMk#cRZQ4Fqjc<#hkf9DDm+h!?#%FOEGu z^}=U_$&q_s&b^o1vy!c*uHcWjPl?C?!&ZcxL&_DyAeU5^1yO@hs#PttMM_riI174# z;geCd)N?vT{ST1$;efMtY*|BBL}c@=wo6+JVtn8}?OUGMPrw5xT*rbY2*sH|5a4U= zHIxX_jqSF;1y$;pFa=dzd0lS3AIRHeICdy&@Yo)BhCG4+m!N!$CDMnjvMM=J!s#Yw zp{Lhs!595d#UPtWkQSMumJu7FxcYx&pOu;Xsj}E3_|}#clD=0#Sz?zjjd7X{ulBv& zWKshV%oPvrU26J(0Yv~GEn~ZjU`(Qo)fHHb)ybU-EZSFDP)uqiEG70c+oRw5<4YL# z=3eaW_}k}=B2n+0{lHCj+QJ>U;rl+}F}#o}(1|ZQEd$?TEqw3ulY?nwOrMO2(cd!m zjjgRQ?kx3lXR~M1>lOkZi^?kkegjq?O4?wg3cIt<%BifSsrq|5tM4BLpdtD|)y(~DLdG3l8@Z0+SGI8njR*&;7M7)BB5^|5LbX^XZZ zuT;{tf>QMowgvUBq65YS{Kit`_<|Up)|k%=`HTsTv*A@QwO;(QNsBClRs7uH3BNw> zYaPOb4U?tMO_Am>QPT$hC14h<-Kb&(oO-Y}h~_bFWN6EP0>tc8mX5Jupm`=7a?;v$ zm>yO)aX!v1Gbj|0#V}!RPxPysg_YFYYIE>oAA@w*iuyXgMpN{7Y7Bmd{iv?DqQ`e8 z$J|7R2K3k8DJ818g8OPd@oWiobNf$xC^%Ek@r2Q3k&%0-`VIqa1PQ$FK}cOyv_qtg&gCn(Ra>C^+W2Ts5>;5)Sfdm%J4M$;Y5 z8uaIQE*-F*w5sJ~<`XayX@d!FEt1NM=GO@2DcEx_N|31|7LH1=Sj$fq@+haj0TiR_ zc8_}BqDPCapu@?{fDFiIauTwu{8&|hPf?**?{jX&D4PJ}-8!0J)JC_C07O1etRLiN zSH+ZB=>L`h^1AdpN8n=4x?TlH01#n}lL=Vb5p(BA7xm~I>jOwrq|P$Hrc}%|RCuxP zMvk@D;!(a?{_fSN`Uo}SAdk47nfiiWABOWfSl+FNmxYaFt(J`tdtQK~2hUmdssTdo z?tsJVS^k({dz_G@SGYuG3WXm^$JwvskZHT@2!^$TQ6fuO!kZTtf4X>@3`6nCU z22+f;RMQf-Ocz`J7Bc#{Q1Q&0=??FFIvgC^^c9vo%=RzAFa39a)KPN5uT&2LB~;QAP}GQGOj1vT$)O`iDoi-G+by@=py> z3w%MAhZ@H0Yj3|8(%rT;C|flB#KArDu)7PIk_O8Mr9SZo0W1v);5|cgd|9)kF;A-V+4*q z?hPrRKhq|ky5V!>qY!n$^Y9` zOA`7YJ(i4)@dMhVorajQfP5A>xmhXYrs>oP3Ap6Zr84;Tf+N>20(LUS%Y;eMPEo7! zBbDiBZCWb`IC^nWY_obMofFkS6$?#gAlFODiJV)D@?fk+eQNI8;SNjJI!J{jroiWu zo+Fqi*8-ovMfd@IIZ>nBr0lH1$lc_idXkmU*Ny0C;W!B+AmiLSb{IAdLy# zm%Rnc5W>elG)S_XIC!a{8pb}riiM!{j;|-vX#%MgVXmB(JHzPq#AqV&jy$klg`f&v z$rfcy+`9qb%Rq!MOw0#;oM|bvOIhm`W@YXR$`Nh$uytR5d)6*eyy2h#PS^ z7`gm=>=^;(IfadCJ7W$^<}S`X4pHM7B~7{otv;L}RNGgyyPZ|hy_CH8diRf8DBiD! z7a>1%kF~3>?xOy%nObfU;#n;wMO;=gQZ=kZM=a`KJc?FHV?lt{S)zWXI=%2g9GcSm z+b33@k~`+0V{-b@`l1Ge>G7EXp8(!0qvB{o{UL#YgWcqbF!CybkB7?9ukNu zHA$&ttxG2Pt6Y2xh_2)$^{)(kOdu8IuqcLVUG);6GN96#!Q~1R2noF;&6KdQY?{{Zr|gdRowfpGzL>Lgcmg$a_*s4k6v4x;;l_$yI^E<* z^~;FDv)hns#z?xF5!7k@4oi^)Gx@44991*Si!Z7o*K>K4g$rThh@vt-UY9we?M^M& zg?nVoLGbJ@q1FZ4rdd8)Z3;hM5;~koQ>{(P7pjc-C?) z+*}9OncI~Q#sbl6L2vwuClnflmz;d}(?diV3?19?EgJGiCq=Pk@G4}_`o;Gh4*2L0 zrhmS@Pl(3g7ehSc*vev2dmt^TuxmnE|8I~)y)`Vb<}b4 zjS=?sN_y)S+5Gc$)gk!q*A=Yc6oTis#TXn>EjL{5i!5=j`HWgvt*mxrK?bf7%jDIp z^F!=aqGs7tn9T?P;i@H_++%pLXL1=@t8V5HBQq;!J|Hi~sF{f9h>fCHxn3B~*gqWi zej!o`ieU86D{7a+NQXaGY*+}#z_{7vPEdK__M1ihni|^-`6FGsd&IKcz>|P)_~k5u zkAIy(a!f3mWg;3Zwqu1^uz?CC>iN^T?1OUolm!6pvQ{Z_9}DUR&zzS`&hN=3XGc!% zcva!qc;F^jD)u8C^c5L}JF!9XjDyQ6YCOf2BZ)-wi;Z7u1fk99W(;xEhlaKY%5OTF*o*?MW)4i}r;bgk1wk zgFCbx-+Bn@d8~mUo{0~o=7A9!29`3}pMP0di2BXE_s~u0=AbD#Buo2Rl-^O(-!du%e%p+?)amY297)L@F!8gyRa8Ec+ zz%LHv4lx32Z3_@*I^uN2n(abvKgxpRU-a34Z&|rgxEdOk(|W*5ia|)TExIpo+2vq~ zV}j^V=8%-NKPuIXlc)I#(NdcI_EDC#f;^&W*ePMC_I~yW&}O< za|M$_!+jJZOvulhzX?9D)%ahPEpgC$dEkB&B~1639?D^?=}nqNjcJqgKXM zqn)Jg$-+&KE%k`jR`^0|^jw#bOR}oY3s+%aTZ%V}PU_r`*aWx2_bLzv2u)^4LF&s~ zZp%+AH3?rEI?c^fV&z06%QtfiP(_KC~u*7?-Ah)#kok9p3knV~NOL)`R(|epH4SBdLDU6z0i4NpSVKAV??| zjGpXpT@b8kNWM$8<}Zsh(i>iPo8Gakdm8V%q+MR8Z=o7igYCLM22#zIm}c3*EbV&R z1DF!mW$83xD~=?(9b?7A#~Dbc^q7qoKH?y_}^LYrq^> zr@ClVy>i}Zm`pw{+>s-v9P zu&V~^rhK*Y1J8?-w2b{u3#t#wDgm&~=Q%#+k0d_8SO=;(`6~E%YrM@_Jlu6^Z>DjW zk}0@LkXc3eA-QvU6COR)_~%%4jwg;KWSnMBiIK-B;wa2zEaJVa>c&^I0J`ZZEJt9c zztNVwi)f%G2Xv-pz_@`lP~WiZpcE5_2vHW!|t3j6YZ3JQnt;D?E08#{Pinr%w)%nMSH*Mplm8Q8$Rax zdRJ8FFA)iqCz-E;)~1ILqFgOaBC@R?@n4cr4c5=Osd%P&x1vti?B~)A^JV)VJ&Oze zukV15p9P95P9p}BD_1DW8@-2#O>_R@4=&_{Ghz=;>< z>jXdjMtT)eOT#WW!k^g*#;Q&$?uBi!L^O5F-`o6rvRgs=5uvkB3-g%+ajP{jv0# zq@3ZHq{PMSN!$O|&ST3db3Vms%mn4>%6mkGD?Qk*I*YY2@Y~PLw3wg$l5`}iqHb%k zd?Q~g)($4oCbdgGtp3zDP<0Bb2tGX0oXytOt>fLc`=eTy1omKzT-=prp1b zrfDNNn1G3ASsv)PbMkuz!;q=V2*|8)mc5cdqefD-Odb13M`UGbYA+8ewdG#pzl&qe! z7`#=9S5As20gtNF|Djyl1DzpJ^Pm{%>DMrd>(e)Lgw4TyJ4d0G)uQDm5454?6rkc_ilgAx`b6j9i8cU#-C{5r-7?;NO>*2utG}X#dOlHHnX-!}B_i`t@`f<;H{``mTf(ON_Sw_!fz(xGMsqZG*8UW+HjD z(jXv=HiW7)m0e;Xj<=292BXV~A=dc;O|u>1L!%43zls*S!W+o05)g3u0yUX=YF~Gy zSct_%mw;xSrLUCPYuu`xUel*r#zyDH;O+WeQp`Nk=e`8UF9 zqK0o!t&9@@6C$g0nhkv!G0l&Ns?T$PHjv!l2%owJ9AyBl4+BxRJo)?t7pX=@OCZ-+ zg)_8c_?-`$zAMcVA>q$0M|FHN5dJ%`x+9?5KT3{H#rWVvK0gRLu|6x^GL~liS7qN; zQZ#Vm?h409b4jxwF#4fCi+V4!#S9w-mROwjs%p`-Y|c$<=sSF1O_l@V2K^etBw=bH z-IIbP7oWgHty+RtV%Ylt;Dy_6D4(I%0F3QlB7JMY`~P~)Cl{v!^|MW0p0z&dl=Gv# zStPH0?UsTU55lnjL#HQeW|W5-0TbqBc7q4Z>a&i}A(tTl!pg*CK0!Mbe?5LByN!3F z;XX6Dc0=^^UsXh^W|Aeo!ifefinQt`VbG34yci>h{<9von=2LAY>rWSFb z4X}Wxr(}KTTs%+{P?2jT&QIYmM~k}LbXLKyS(42hgZ@#?zG~*T(b;C(4N2MMW6Pbc zq*4zob(j}(54Oi#+8-j$>URHjpTxdBI0@EIBBdMs;yd*$kI?5-LTu{E*A>at?&3$D zI;Ca|c~nOVxOwo+3b@5~s7VD@p6Jzu7yzVKpLgoBbhMy#vew&S2``dZqcma8ll}?-_bD9$jc|bX$f=oPoZE&8D*bBagO#-Q@rx zJIwz@6jXAUA_CR=Q_zYuPW-NGEGwH}%KxOf%yfoDd=AgfMkU&^i;0c6 z#*vq$niaYeAL7mzgKu_f7gNa^ZMPU51TtZ+v3%pYyvb`}-I&(Y^qCsc-$#WR?A`g7 zaN2c)G*3i(A#X1s=tVjpDT%Sd;jRe~2n zJt4SPXL#f^$_t)vwa6u-yCrk-TR)O3iy7W#hNwUB%eO~n*RPLDVJ^tDRMI<2+VZKE z=~2e7n`2UnnsJVrkGnCzA4+hZ!EI55Cg0A8*-FIBaYvQ{X&`Wtz=VnpMoW}p zMvZGJsCoTV4_uup`N+5M*1Gteus+_^bcV&{%s7Al5_^tpKJ!UsUZ+G`J^-z5$dup= zrpmbiR;vtK#W%Uo7PEJ$_BUJZ7jZ%38E!uZ5Z_eYV&MNW&BE#)amb zubTg%0^Ly?05F$=_aivwEwS!e?qe(0Shd&~Qa8D#!HcqEIhJW&Iz*1=k774sWNEHk z-8f0uF(>+}FIyo_*h#LV%vSGATa91A^g#&y5q_KQh=<$2R7fey3SoffGS+bfmk%=S6re4(-4%1`w8cAx8E?S1qrSAXrc2oa#fWj$y^MG;;)Nf{MqaZ@ zNq->OqGFdn5x>zNMM=qu1E-N?MkN+QSkjW+$wquj{^hLYAHuCX$XP>vDKpBk7ID8{ z079{ai||A?3_YU@Z>)_sQ`6kipBkO;q8Z%O3{o=R0&`X=%C{9Xj5M~<%&3^6b0xwv zMf{5XWcEl`?1-L9Lz8W-0$zR$AD}qKU=w1G{t$5I>bDQUvU`a2>VKONpjY4xitu~l9I)0ph#Z9CWz-v<;FKLVjKo2GQ(JbdG2{)|P3j?E;sB@87eA)JH zqiyb0zW^C2dhit>Y}S~THGfRLrMpFgAh+ywHDSHV_MDbj;*rn^aAxD0acb9TkQ@`{*soM*w0q2Le|C~A)*?^OaH&qk~ z5$dkqV9r5epJVf+zCY*TyYSAk*v?fdkP;A=IM#^*W1d{4y}hSNCJ`eFVwMOf9#H|7 z2dk93@>*L+TdxRwE__=i2>uYi_YUAVgq~0 zu0;BzD)LZpzL#W^pRl&giDsqP@*D0{=lCsz9y?`QKa%4mA$|>(nBWB0lI`cXdMlBa zicQ4N380@Ub$oZ~Ab`&J1EvayQWUJ~*So)t-;rQX^Xv~B;KID2>(b|OnRCTsB<9`fdmEU*Zg57R(6^oqWy^o>m1q1ao>kFx+#+pqeiu3Qrr}sTFbCBuxaXC& zCdS)eW$mHrdpQ-WtiMnI7(_k7A!wZ*5kuT%M9|V3Xa<~g1@HNQ^PO%93*xZEkTiL& ziNcLVI<6JG3e^l^douucMK8PbWg`9CV}$l#DTieTIvyH_xlS zk@c1D{gX9;31K$G8HL;$ug<>{cp zHH6s5%ZjS!cjD93AXzyJdHC7Q5HazicPiTL;|bj%F@l8N$|S0?qW6IuYAhSA@KWs` zLBn+MUL`$AB~c*Q?V-p?fJAKRNy)(`Dn`foD1nS({%*ut!s0mD3m(MN9}1zu8zwC( z?_1F5Ky-Vi6+U+6uwvy$Sn`R5!y{y=H|qIhb?lD4t+aY(Zm7!sZpBIP4y*b-wdK}jjMxWJ1pSwK}WJ&m$eQ4*1>CwD|T?v7q{SrUqGCb z5cAoY7JayfTRA89IWCkUJ~Of27qXYKWzE1WIJWVt?0NRU+oz>Sm@&J!eW&@cE=ZYR zu%d}~be!h`ReAG#=ri$yTqI5-NS8>(TKbj}p*yBnQbLb2V7tNB?vpLJvi0}!1{o)z zfk&%6gG=j>Y|TJ^k%IcF5tf8j@7*aCq7NH0UzajA8NGtWU&L&_yST?hky>slHcp{%qg6umXV>6-?ukHxdl{p>pF;(B^ok zxDShTkfpAfPXpA^kC22EAhjkt+ihhc-Mkhbm>!0L+!l;@6^fOp*ufp>02s$q{T03& z7A?-UhU8&aT|EPXweIL+dr;}wwHx^ANwDeu#V9mPhfdR7svk?m4-f_x#%%DND8NhX zGS5E?-q$HaT-u7ofEQE)FVdD4nY&gj@ZPRF?}jE{>H;vj1iqI`uK+&o>A^z1lCWK> zcTy0IyXq2C=Tr_TvRCD_FaR>#1tuVe&hEF(Vyq$iX0JrZ3H{p=KH?iVv}&VK;RPO| zM0(GrIDed+bU6M6=p7~ZDx~{9R9WN&n_1_iPiy(lw#}flg0z3zlR{cYS z82QF&(z+B}sTq8)Xm7X2_mkVJGAZ&9J1Mj!$HhKS=IpRv5Flhr4DEXq)Q#eMYH;AjeZ)o3 zZ>4Zg@#t2z;UKRe`9*ckXOuzHO&r~W1q#~8X{y(5dx+3s6X6K%aWx;naR2g_&Qb+v~u0?vh4|; zKDRL_#8uU{IGhC}umqjY-DU7Nv)a=6wT@3((c3od`R&X>{b4&64V%;y64F%{c$#+l z6yBR{l@N~GOfi!Rk=Nsc_0Q64pP9+LI(WrzS~1QcqSfpfaGeF9Cm2Gfq!M=0&FGtz+x2X`S_V6Zjd%EE8LG;njbR8XUt`@{e)v)vAeq1-8KtD5%C3R*}R|~J96|I%V<$3L-ApPHb z2SE**dUFPZ&k;*M`-m)Ms`YBp>^mFObUmW6t;y<*>CXG=lj@1QQMLwO;0t-J4JBB^ z;ldNS;C|UYI+n}fh1X~vS<|E2h!|RRXQ$3#T#iM)PxmBSnW*w=n%zkb>JZjNen7qx z+`Os@8#|po@N6*%3xwdZ(bJj+^ndX6Jk#Xo2Mbp!+WEecdT9i90A%cgJZF`%)=u%h z{G#uDh_P!*E)`*l+MIT_T+V|OmRR5+E|S(xMKoD0@lRfE`KC0W6?_Yh4Z|B)&@of3 zQWr2R;gucz6cr3$o95lEDwc2xT{xkh;`Q)MAk9WMi&3||=BerVtk7_3XM7oZt1__^ zh%CRR3Zv15>V;5B-Ru|Q%K1M}`!!->&wCG>U`WsNI0 z6|v17`I*>?6^SQg1TbU=tu{; znW=D%oW++(g58DcP!MBZ5W*UpZ{fe?pRD-q>g1P{I;)NgIn}fd0)!%^(mT_v3BVD5 zNXh?AusTPf87bBWSbUD|9q5VK>hEHBs8bc~#!D$Td)~P?pNEi~Pfo^Nqzv(9X1oWa z6|W%4^m)kWKepg;5~pUL71LW;+;i`bP%M^zEQl+MdB2JX(dbrgsmrb2+s`CF_UA*U z;2%6h(K6ZtM{qfq=W(zVe8OIxgSVBl>_*$w9Mw!-;44CqMUl~-0+4$X9chHpU(paK z>zAO!)yRpq@bntDD1#B&Jkhej4w=v4(#u2Z2J93)S`P^qfycD&+8S(Px|D2s2q#E` zk3FUJ8+A4+NtLoEtu`v*g~xc&CLmXYmxdv0OEdCjV|4DwBO5XIZzw+HD%q(D%bAFT zN~J~h$7tsQr7M9rcr3VVF+XpDD;yBBmygE?^_*#Jho2s zOVT90%mC*Bwmh_i3fqEA8=St)A#ig^|5UPgN65pB|@NSODv<_)mZUjDK z)Iy6TZQO^**Uo(?4HZ#Z=-b2dkE%wU*?!gmKF82wj5YJBQG}SzyAyc5Rg2x;lv+b~CDMBBDE^C7H3`9M9$-ia0O{k&C2op#qY zZjnvz%cQWBDux4eaj3#+4wfz}7)E@_)I5zA07pIdh2}|l4Ik$m6VGU_);Px&hs+Q` zh6p%n$Li_B{|NW3pG6W>jBH3=mr z5iPbYqQ`kni+$6qd$Y`@ObBbxDo9GUPX?XR{8~|~IPY^NT+D-*3xMAyuM%Up09NyJ z0BB}%yv1w_R4RpS5OAC^;!m!Cn%dW`Dv9hn)H9ekB$^|KSAaTTQf$9#~ zDL(f28~bxb>8n2w_cZ-Tif7k(r#^ME0CU)RD~U5kQEH2WVxYpi{0bmx{Pcd<_8VR0>Z1V1iKbS_h(~|mrV>O#w9{8BHmAaKqlidaQTXjJ zwXcXIitPXkpe~)dgbqZKIw&GC6wfa)anf(>=^U~}um_*3yJq*juuu@=t=8kNE%$`J zE^!q_{2vXuFej%ejQobrA*okqgBi}D8_l=gVm5Q#$S*wfSox>Q4oBO?HGBFpBmrzj zBdlDA1^3q{DvZ0Gbj?-S%4o2q{P5#x%4(qP9M*ONagiW8T1bp%b~VWC;;qJANx(u3 zYZgfhi{q!HW3);3O>%7bT5FBYdBZ!BK{l#eYdCz}RNB2_2eHz;h6ZC>{sR-&$&%*J zdv_?kgM<^K55O}9%S}uL>@`mY{~b+!*65q!2HFd#|a^ z5)1f>lEB%os4?^5z}G-jsg4kYJqHuBTfbYj%;#HZ!t_SPA0v zq-(A8J=O#z`d%ft*1_Co?g;`9b4K)%(j0z10Qk%`o}Z>n`)Z;-?WlB>IXfB24qn1P zM&kk9v1)4~56jFFAHfTx%3ObJ#r9!F1>+1iG?CD7tI0^c_P9VO02^P~Q8=NNQXJ3) z#9(56^;-3+VXB%4&hgX$#Bxo`IM*?{xd%?;-B2s-lujg0*7;_xw>OT#teMMWS!=rC zsMqYpA<(tsA15#qk|P+b+n$$@6(;DvsSgbB)!A&2TPD}S;MD>REpyV|Ok85epW19X zs80}}ds-5>u(5(MZivOM*|}-wv2X0%?T#8}iQ3vexkIko*&ZrswIdi4OQxf>R>T!G zm9z<)Gv=QJyl%$NuDNfPmT~tUS;=`RXiJHYX@EDZ#gkrg;>s|AZnnqaA;Xq)dPMu; ztJIOeJa|n}w0^~w$Q0rjK7oLvYu}7$ff~)?=CWg3QCme*4m@;`>kvUj zQ@2P76JY0CKGVaQW{yP~$TmveW_vNEmla__J)Z|)$;@PZIq%F{CjEOOwq+{ZLmnH7 zn=Bjt3z6?Y{~CYL*%!o*+yGnpTO&(%U6XYd%DQVP_W?rMxwQ-{Gs#Q1o#toTMlyXA zH3*3)TknlXSb^}8|C@zY8drk=9@#n4nazY1y<>Q&)=rze+moiMG;9z8^d@?|azLIg zMft;5W>30IBy*+S_}UQ6t^OgNi)EH3ii+81PdCQ1JUa)EEP_jHACON0SBka{qe7I* z;$K2TwT--H+8bjZ7-}9kJ*JO=&g?D2-u@N{Qf9THZEz@t%9T^IL&@UsR44S%(>G(k zAE+Z=6Y%+G9b|d?o%=$wvf)@%+)I$QgGmyFKGE%pCbP>d)tzElC4jsi{Gb}~>ClT# zMQ`phE&LRCV}+}(^J)hMDj;gJg=Y{-#e-W|WleTCmq(cqmv`u8qEp&2GO!|9*R%9x};J3`=o z9T*~j!?)B^44rY=(rKxYv4i}zjR^NX`2&}h`dlVB|I}<58Ac7W#6RTckC!U^zdw?~ zYwho;N-ENIvtof&HJH+<#JoVl2!W}L@!}=&J+3w48b1*|H~I6)i+dUH&7tZN**V@; z)=h_#FNh&CBdG6a0#G2$n6b6&4>2|wc~e*yw-}BoYc^5f2L?6=220I7z*!I&&OoB5 zpfdDW?dozB6%=g*sGiwr=%@6dNWe_pp+u;$e~X*dkJ`z+lfB9G{q#!YSi^affDd9? z3wZe03cgi2S;ep&N#NwaL~1ZlTBLV&p|F~95A!)s1n~rF><}#V$h_vlO#;*GbMO0TKsrw`dBC?+*+1Rzg-A=rH>a1E-h zbHr>BJ2o-D5C5&Sx58KC2JH*tpn!oLf2Tk?To8Ba^$D7FucNa91@sOA=39IX7i4*f zn}|y8PO6h|DTLp-6jjn3_;>ce3{U}UTL4!$WFuqg=D0ZXuJIg;%rN8{hKsMF*MoAa zqMg`1l}zBtMne&;esaUo5o#uNvjuw&0ISKo`jW#b@8+YEPi`L0_^1&mcX)`~E^TI4 z$G(dA7#qP!%%~Xgi+OJ!PK{X)7PgmbfMZJM3ofI7rQlN&x^H$Pz&g{94h;1}e7r0# z6l~C`9Y2ESYJ$oP;oAUxor9Y_)$_qG>w92@4@CrHplONey~i96+k%5WrCBgTpl60z z>LmV0EX=0dc|gfk<@wZhT=4@7LAXEi6k19J+LFI%lgF_re(Pb7t>i6)9a?vxEE)o; zXKKI{5DTlV_9G#esG=P{|4=a_;f=nU>>YG(QbiMp-eyA&B?dDeLSwYuHd%jw=CfTz z_vtO^w}j8WQKklW8H1#+oM`X4)qL<7mOPOXe&ia0;XxnVz3Cc|{9fcn#2BQEuQp%R zpfq`V2bjD~BnL|xdjt?5{$%NAlRo;Wk9$8k-Lfm7F{2Py&j4 z*^B#l;w69`*%LEY5YWcu!Z>bkPC?{#)7e~RqX+0Kza4Yk%K+Z@{d>MXV=sFCJ8XI2 zez~l#8!)EQO{c%NpkO*F^OFPBzPB6ZpKqnWhSEFjKe#!BgF%>-6N&WWxH5k9Yxay) z!?dX;v1LHR9rO&)OFMA+@awvD`H3Nz{)|-s3Z@tNV(9#%c>uk8-wvJ-WV*5I-CPdL|@L@p3&CL4%OO2oWH~I6#9zI#EdBZk5h-gu|7Qbew8N8W% z7mSjg=CKJmxM#ie%~&X#*gj6QT7++uQfO3BwTr>x?eWyU)57hK!J=W} z=0XAQEfLH;K_5`CQ1rkZ}jhFeFzzv>a|3e(5 zLdB-|FZ2&fAZ+h`louOp{uCCI&BJ)&5$^)(OeS6vy{IvGwE#pyh$eXHu%2FA6O_)T zoTKJ=kY9ad;yU!V-{B%ez^{RxQU-pD-b(jtnzw^}Qn%MP)MF4`e*{G3Pqh320s!kV{d5uP>72*qttD9odAt5B)cas zxE@5CMMlCbwjP*bbFm0l$|S?$Lk8cG#kyQyuYeUEynpXrBeCg*@Tjd)jCv|&zX|aw z1M0Zw6p_0In6ZhYmBfIPGxgHHzHiBvE6Zeb!d?vg#JhbdrQn0vzoGdeB~w{2ImCfJ zt5Ob^tA7bZBAN;0_I@#5XSDvmQbwRG%8X53-vSQnthOLr2IEr$X$sYRaA%(#Qlqg+EvVv<2!te)Qg(>x4B3bi(EOw4 z&vos&NM-Sb>pRk5lgOrX+M{Veta)L(z?!kPc^Ch$_Z1r2mA=;-_dEII!S;_p7p&rz zflWa+YU8sq1A4kY%O&zgnEO?IuU=D9e+=E{tVo@et(CJr32-py#!5KY8$PTmdWCZMqY_3z7PruycDZCSouQ~1+VS^f)KZWE5+NElUo|?kd#Ono9dY1C zS?Aa75d6t#G_I9GhM|y}r{yOT&W;JY5mI3hi3315-EcK-+#LsE%a$I6DRVg61xd0m zT>IJ5KNJN9sj~K#;v-+=1h}MA^Qcm%z&`G+tN*3h)e(v!n!oWF zRdnHPDmJn^^;ISnaSCc$?mmO4{{Sfm&;1>X-3Ccyh*7@nTz^YrC(R_V+&VOC_Oha+ zJe1a=V9Z(KrkPHHZ`VRy+XQP=7;o^YfF=*7p7+0sRNqwCCuX`e3ZK$SGK`q{MJd)y zf#d>5rb{V;!uA^MbY>#0&73&X)#a#grT(i${wx&_9zS%+`V0|-OV&OYi9;99TuLb| zOn?@~wLky&v2}0!vYId{eFUx(VqMrdiDZvAxZdKt^2Uak(3BfxXclvP4&&HyYZ#=0 z#a}70SgOzxi?$D7Z7czpz$^zQWRqT-%;zcU+-c;WC_GzGXzI1$j9FtkD10KZ#tk9~ ze;@cZS;QlTu3rTsJ_6=j@KH>+YH^Sfom;|+GZF+YMUVc-1434TvC^;H-pa@SjscBI zhERrte*=B#3HYyz0jfz+mhwe&5@Oikl|~Gigoa)_RZ6s7*5&@#2jM>R8F~h0zvitV z0eNlFf0r9Dm01O3fdNTW6zl-qw?((xb`Tf>Zh;Z6)^RGW-}y5_601_fEeSdx;DOQF z5#|ZA8uOL^NEtB63z#$OjDz6Zfm?grEfC;8oHBOaLH@4klUY=(ibV^2z2-uOJZ;Am zYIfq`gv`U|4@pqgM49S7D=ns3>_i{Ojl+ubl-77`f)Yv3cex4oUZLywn>&Bc7(>Ao z^@`wg)vgWvqaA1N5AD~t21rnz>oSG1SLCIi`R3PU352V!SFOw=XN?prC4BfQz{R}Q ze`)XJ{GwS6JX4stDVU+YkL0_GRsM4S101nruUsUSifx}kzZ)V!XOi7(%9cbN(!IhUvn)K??tsc|y^6o6DZb>=;>*JzKu?hB}2H5CssWO^fAdNH978VxroPOPU1I#DE zgg+lI@NudD4R-%O)u`61t<6LMT|Rn6bQH-$Bw^K>6cf;EQadl(XBw<^hWhXx9+={V zMM=1=LYgSuW2DseZ#@IGWzix2a=Pp2KrHA(UO%x7(5L}$fk5?$y}KVMJP@!@%~Jxe zWG9;cH&$2nEa3zVJ5}tU3GVf8vV$meRv_Uqmj0;LH~T>@+E&zm{N)7D?d8EonM1PaoUC4_Wi<-VuJc*uIxkgFadsVJ?Kp z7Cd<%>7LPbXbA_G6n3_;S{MW^gy7+{K8n26rVuU=fy*tpG0@2Wfl^j||Lv?X|7jJc zuU;Y`LaXlC_dR%k*1p-2$z?t+m)5}oBGoywL|tqt5cZ$7e)&`~%d_6%Q_Y*R#^5)z zkDWMf^^Ve4AtfO4eJ39mncAt*m&0n0yu%<@OsAkUpHVPePQ=kzJu6zi{Zg`~a0w#? zo_zJOWU^_M3k9-F+*SBg@@zgnLORZ(%jmf}Wc`x1r~szMPz_edMG8ptr)r8HUR;Ax zgy3bBdMPwzETE5jp>iMqtiIU{@E3{x?=Vc1JNqd*EQ&sZ7wSJ1AG=<+k83zsqG1t2 z7oCs8n!j)8k1c8}u}RZ#KqEelt$_WQPmE?VNmZ89-hGkaem5z8rdQ)C3sA!CTzP!v zV{_fN@f*qtA0+rf)73B3%_&SOF56Ogyv3_r^b4!gKA<3e$9XgHKnCe-O!6WBxlG-< zhRxhbNxfGDjSV~ZLq6oa#4Mu$j1Of?wI&o_l|iRc;_M$)y;B1#d@~tu;zulGp?Csr z`rRvp8OmO)Q&hsVUU0B1Ch*athj^n~H#1b~AE>*;|MpvT3&LGRB8r7FM~ZJ$@MN2y zf57PgWk0a9W!g{Wf5=>aW&=!*}5J`hhU&jqU z6K;Ihq93W~o#Z*ge4<3Bs^0GJIoDl2GUTfXlJvgcf+YMOiQCR{`|a8;uJ-M#eOULK z4s=@Sh1IH6DT7E~|M0}GHkLMUcJ3Y30+^XEmg%ri&%D>e zwPJp&U{ZS?{J{?!C+^G5??^UOv$g7$krLP#7Ko9CzXuvOcw)JS8~llyZGvIf7V@K5 z^1<($9ZoKwP%gAIMh#HSAj8#NtzuD2omRMu0rNvyYt=$zwM-tV|NrOUsPD(G{ONFg z&E4h1^0&Rt;JGF2zTQ$ERcY`iz7^e}mPVJ;r%s(Zbm`NlPMqZeRUOkPXpJhqojP>s)2B|II&|sN zr%s)6lVO|$ze8zLQ0ddBPMtb*>C>l9ojP>tAM-d3?4hDGs`_;4)2B|II&|sNr%s(Z zb{b$I8kF6ol>%xYMB?ZZEO5CllC!IqNm--h8vFPz?`bS~!G=Hvtj6=rn-X*;m(GxYjW~2|&trbr2hZU7J|M>_s37 z;HIzuPerAPN^?c4OyKiaCgzhgT(%|lM2P?d%VIzs%B<220cAIr%T*Gub%E=v`7l|b?tsA&H~L$@p6+HjJ6IM*~6|Mtz2yvsiG5$&24o; zP8khH{`3S8&5bIPtBiL=fKf3mF)|Uf^VxPWPOOuDuM)P$P|_|BsOBZ<0He)IB(oq$>r6 zuOM$dwXg+@7l>a8f2&O9w+N4aT~~)fJ({`|8>Iq7?sjv8IW^jaR&{lfo)$lF^FL=G zIb9#+gIufFCCbGtlrds{mA`pr zZpEjOVrOcatIKHN;Qsv3O+qwFBXKsa$G!w@8-;U)6)*7v{%eeq zXQ|d;en=?WZ3TQF&Gn90IiXg7&xA~X`kQn)*@h{S**m*OAaR`?P_1QQkh!x+b@aB(L4?sC4zew#z9RE%dNU_*1!l&n`C+b z08+gn;vBdC00095&7umSUaAMa9z#~faKCvHuL_Yj6SXL_%~q=>9c#u#8wmv1{gYBO z9;%TkrKl}Chos%yz5X6pW2A;Sd(HwL3h`SXu>aorFi%`-RW41d}j^`ahEl!)C1vRiyEa9lA;J zN0jE#ovBNoyn+n#*G6m+LQsc_@dZh^eSK_!*+~}|AC&5=$m;x>uOX_yi)OOT^q0{% z?dFbimhWsUt~BYnH;?~ZL_71Xtc^VUSxR!R%&V|w*<;qyqyg+1*ZBfJV?DD^=Mf;? zN+q_Qjs;EZl$@WxsKbKn{Co<2;c5FV0M`^m!ZB(2BoI2pcr(A2E$TPDL6kwz6a82G~N%I7a$rD`V~->i0#P zy@eTTI2J)}W%#`Kcd>z6@dNoK758*|=d;>POWOPOg!6)b2(~ZPI!5TEPlNwW#d_?x z7H~8=^+??DK|@{wtugZQc*0_(!_MQb^h3sqRcH5^?oFsOET}e#6D1sM2_ZT({Y-EJ z|EAChK7GC16-7P#Tr$QJG1X`Bbf7>*%l+dkV|cM?XOp0lE3%|5r};{RIEh~~2;7}9 z7Ma}2z>!{KSr>o`!!eMa#7Fc)drPjFQ0CQ>qZw>5<*TqB`VjBhL)>5us{Qd)0NK6% zqDw5O$$DZN9!aXXeNt!pCy^!9W`K)pD21zQ*neAh(oQQiVulwf z_Oc|li)jI2o{g?;u=3Lod`%^-)6KQ*qk^nKw9a^}RQrjnT=FbSUTPZ_jePJ2eemLnRw% zSP5!Yff|k9En8Ls!Pej;HNnkECYKSQPN>-iQ$K$D89~FU9+*!jfH^|9TyZEVI08mn zp0wvg2+QsO4W91QuVR}0qXo7BnfFw*X2dZPd`~y569b|lEV!Tiy6{Jh_@jVbN|5TZ zkp1A)M+$T3LhdW}%A*~i3|FI@15o_f4 z57`;#wj1Rh3n$KnTeV0IA^YDdJkz)H4Zrpi`h{tvMxo3Fs4!W5{GY{ZwyQs*|8+Um z;W(-xJf9gww4=En*>o%1P z1iFr^3evoCnQ^|xVxF&DzUt<38yQyPA^U)rr@KA&+1B( zUT;(MVXV!)iQ;tTI;~&Vc%}Caw4CQ37I8SQM@2*4q3a~|;*=KaQWL+eV!zRirs$m+ zC18*AEhm49*Ji$&4^V-Od4P0&1V-WwNmz)Y4~UcN(}qByP-ZKS;!kPtvj+nGtnD2WqvU{<)dC~cxsyQVlgr-m#!ucq zocde4;20YSZrO}BdIsZvQR!C?_|;8Poz~MqMt^se#~%h7vL}>9vu_(PZXQ?3OUY?b z(&_(?Hox9bPmuSc9z?gVv7RwnF&lDlvECkESuUC#s>a5gBS*_&V3$pijKjry1cjetLGg(VVJ5wH=!C??$9T6ZzLt@w_n&5}O0 z7V^%D)&x~_=b^cJRh(0rXJ{x%ng2RT^3e;A{VY?kY37Z|zTO_KQ1e;+P*vCw{7A-p zf~w-@1MCL|P7U5m>!trvXX)sTL(cA`#FkePCF8K`utb`aPVf&|1;WKiF`e%8^(l_1 z477up_m5}>7)CwG(N24;><{yJQ&09`yDJ_1YaV*PSu>g4%8qK-zoxqn84#fT_5!H> zoSf_{C$DsLFgAg8XXso;t%bP!)m>tJ;nV)IAu)WE+=6C*b^p&MJ`F1gjbHD3ZfNLa z#dJBMZ*3{(ISJ@2xdvvJ0$r^<6}jt+kVEibzYjE`AdWg*bMo%pFIJgqK`W zJRaWNof2clyGzfm`|O!%Yw)~~KT8)WX1BEI6vb}gM~VbMP{;-^lo^B4M-A-w32OeT z5&^Nq!%%4clbD<4aP8RE$?0dTy|F#dx!M?!w%dLx3er%GJ-=Ic-!2JwYeHmdX{}}6 z=K(26F2gAvxGU78xvRSXi<S2t2`-HFBFnh0My~k3}y5{gM_KqKD8gB=$G;i z38rfT3{H7rfRCg4iF!6Whu)OV0D! zfi4^Il{db4!6+C7$~hCpziPNhRTwFSqbTAaph7&+Ilc<45$R{$L%x_yx>|i3F_KLs z^Lt(`GNWZOVfjV0`Zh^8sg%#CK#`3hy?WNHM%<0t(=hdYOF|9~{ttA@voVQXkq zMSvS#PIZr7=Y<~3p5pOec)5#7Qii*YX)iy)K0 zD>qZ+D)!0_JH2G&)F?BRx1G^n!A&GCfADdoskbn3G!R$cjBKSPV*e4d?4~se~dtUkBj@yU-c5J|MmYP}1HZQIu)1mD96Q!70K0m84{pu$W zXivd#nGhh`a0yLFhsNiRUE`{~;@SsJj8YF%;3HQ&Bs*X=hD0sWE2^i2mvU4#A$Nxk zk7UMqLY8^)Un2L^pL{lP80Q(k#&|_YK|98K(x4#!fGsgjubsr6NM|3DHe+$EkD9Do47MAD<*|auIA|Itm=~NX=sUmtPbT{K=8ttevA%+Wi`#v3z?VPjDfT3Uu64iUoDN^;>d_x~ z;|%crATJHYA;{t4twBG|r2Of}@+={=hCxK`zfbL%J3v|Ckmytbo;u}l=|wwnheQ#9 z=>GesIVtedzaqtzSFwowi2olq zc_yC5*xeV>5(k>Af`Uzh7c`AosrPvSDg<4om2p7NQ&w`q39LEZPBd<4uK_0z4DEqK zxP06Uc8Olw2f1pGG-Tdo*n%Mi;bm1V(w4J1M+jkguhKR1+{Dvn*|B9vo1q|;_)M}TYPXtx>LcUc86%UQ4pyKNwi9^>~ z`7>AJ8s_cp$GXNk)@fyk*0EDv`+DBdvrit|H7Y%(Y*IFL{HzkCLf<#vQ{EmE=^9S4 z!$fEuVW&Q3@R_yJ#$?Ch-7|KaNQzWgV$=coD#${`-t#7e{^7`1W%9;9efbzHUVxg^MM~4es86H*60JKPf39oPlBr0?o+@Z|;I-AfQVGo61%Hut&;%srB zE0|G^oMf)QdXpa9ti2?$9TkU6B;zE&*s$saL@`xg->qC;TKDHP5hdo}U!bsx8j?@> zCBcdey#w*{SeLzGKx_8kfb_i=8dv7Y(dw&m#M4!;y5P^iHJ6#?Z7F=_v6!q1EnLsN+5rly^Kp_1%^ z5Y(BiTr1MkU(@KWS-I2`Ho}u>^-VK5f`m{rI!rCWFvO`y=`zK!4T^09OShaV$TP<+ z@6WaE3zyT0JWK4h3T}o|WsY{Q;yp0GMOTYDJuSPR}UY_gQs%K^`O-g5LZB|PX zwDn#+2>uk>O`N9&k)vp|9{gzwyF-UX-LK(W`M7Li*53yNv3H zIP5W}&z5cbloqALJeAI}4pHon-?3EVIr9VhMzoXh_n$Y+`K4H4$WT=gNwg0Y6Nb=e zWB;=5z7Lk&{a~rS>)38Kv0V2Np(Y2nZ2gW;=$YeEUz|srC{B>6{@0xS8{ZBraG*x{ z;?3vHKnKT+)%bm7dOXB<85MpRsZFe9xl^BdwKPYhkx&hHlF#uOh`;)Te=tRNCW%o4cE@UuMq$+ag5(#BQsV^G0u`ujUE45O8eD0M^w+s@+?)@8~p_HzjQx(pFbA@tIc`MG`rVn zf-v&CXZZA7VBy7;>z0-LIitruQfmu)HnKzf=w73^B_D)GT->ll6T%MI6}}qHNvVYD zBWUzq5{kmvD5Dlgy%r&7H#vKrDADh>Fysk9`i}J9FBQXq z*IjXMT4-EFSy3&W)fv}osWr9?{0!qt#@8D|Pt9F>CR@|AuKI#LwyHu1P>v39+lt3? z@`BrOREEU4Np?;k(%A!r7t=8Xo+H(uHv!sNU{UABGsBzZA4GP;0-l ziw{u<4H@Yh#tj}1$4cDnh@?wiW^jRYEE6={t3_Y+z3Q#%`9jwz!*~EpkCxWbAwm0? z_V?7BwuiNVvL?&7>x|{arDuHB1#UlpLk|8Xu@&^Z9O?6UTOIiL=+o-Ng_Emov7w<( zdX3&tExymLu)vX`F+~KA;-!d4$0F_2@L-vq@(esc@^ud{-VdKxVj%x{HxX0~WA;cf z#$(m0-?GlWF$s8mKv235!4tx%lc)m*T3Yz;e@`+vcur2Sbk?j#) znr65M?I*94o&_IW2d>x@{g7{X zml2<|o7O2`;BbViMKLWZ{(kquAAv}9%xc_oG9T+O+c^1_5qwAlhZeZ(Zgt?g63uqX z0=!wXP$5|&e@l&*pFz1j01ZO?gOoXq1NF_6$E9x$E3o*nj{o%kulZr~B0obJrrHVu zG|eS!zm2eNi)bof2d(n#93JT05{;SyidaLInh8d} z+x2d)&*d#__SiCXU;!Xq^G|dZqfmm-I{9uIG&+EZP(7SiHp=C;X7kadM?Cc$5;NGd z;FK*=C0xH=-+5F0?;3YP+LJQ#*Jx}6v(zx2!INeq|4W7K(_K)h9V`->9Z*IjHWtrV zV-|xg!%5h<%SM&oG)u>JT8!W;p7De3FW};i91cxjFvmH!6v;N5SB0QP{>~;Z#^iHH z$(~$2-{4J`ZIdnSA~H)GU|+~O;)eq?FzuVGb6OkFz;854tBTQxT~MovgeT9ttZ;aG zI58P)EHp)pP55e5E~le?BnjJ-t+md^or8-L$0Q)XEDddy35rvzj=4^Ftwc^ns=A+mi} z7pZcS4Y0DY)YL-!G>Vn*X1k-v% zth?JoW%wok7oCDCOWG1$DS(i*ul)|y<0NH8)@7g51gJ=u0`UKd#_mDw^|U!|2bP6||0?#qEuXfp2F+5PfJyE# zJbRj~ZvStwoBzd_uy$Z8;hwV*iNg<%N+<~$RtR{KSN%txgs_VGz5vQQ{Cmiwe$9Xx z+w57fj+GqUjWnB(8hScy-c02cY9e9x!wQ#8FVrLm=9pdFjq6w4vZ1kTv3h^cuc>@Z ztl7{KZ7@EpukxtRudUMRHU}$Lxp{!{2p5q#0{VY!z`gDa&$Q6M(rA;x7Ry^5q&48Y zN{6>&_J%|sx@>=#eTHw++K|1)K0?=^-&~w?RIoEXd+CL0?8dDP2Fpy#61CMDGMCM1 zhBq+0EoqJ4_1x__E`9s&9mhu14E#6m`67?l!m~@2I|p+oI?cE?_)vA0+v!(8T4-H=v z?~9@+=pt945X`fWHg$9tXf{%Zbv4$rM^Ey>WZ8li@Z3f*rxymg-$TDeO`7=dok|^? zWft*)-@LYGjWh0Bd{GHFwU^-`WjNm9;7M5qkrk9Q_BY79?Fq+v(uFOJzD~|4@J z(z7G(p6w!ROSbI}rKCx|qjkSl=tuF_AOeigHuuE};HRAU4ux&UB5tRKVj(|s>f&?4 zVK<9s_8xy+_ew^Dg9hS5H|yT!=B1Fyh*)|zxfk3=fU8NwPR#)9pLaWdGQS#7LEjDn z-=Avq>P%_^RN2k^s!&7s5xCQ-3b|H`1-s$mwEy=bc%Nnn{+4(_iDxtRF%tQ`AZfIP zvlA#OtDK-rO`&dV>e00g9g>2=u3*Np0zQyV{!DKl7I*_9lPXE04e@5(@PG#D~LYQ^h}c3R5ca$7S@;$c?hBUDyqw1#8gqFhlWY8?99l=i z(Eyq@=ThNOKDucZ!Rrkf?#qym$zcO_6*}c}bY)MFg*co9fjcG;FOC9vtnF3)UD0y8 zpKs?pL7REO#Jo9$Z(;t3_r^+S3`b}etJ4F(|5>!A4ose*8+`V&PxPTy_SslcrVj8$4Y1j=QM@@3_eA6W)aZ=cXrGm&7^?8$Ypo zn<*-Xd8GWnx-M2dYqEnox6ds#Gx2|I9)&s%vpSW?yere_{#k3ZRtSP?E5}*^4k+&C zSIl!Cpf&;E+7mnXLyCwf^SK>+|DRG&TP~j}oM^4>`1K?7+vwm4jF-iH#L65Y8a-G3 zIAegz4jV}ko|d8`Ahk}@>gCv+9?0vu=FWk&9Ux%IGjPpNlSYTOsiV5pd9I=CU_S&E z^sQ2t`rfvFWtjrISruPj8aH|V%#q)ZIN{?NnVD^{1!7XuV7MBcpz_zJJV7skE>2Cf zk#Z$tbaKd{m|e*O$YBbCs%a_wx*I=38>Ku>JS+n6d!;J7%O`aBMyb42d=^L25LY(> znhQ@%kmH3Q*K=uuuia4-^E>n=cz&B1MAMG*yzOa4R6ZNC2<Ymg_fn%_ zvoIXLRA`dxib36y`66l?Qj@A5?pft6-I^J&3R0mTZrfoSF00t~DN+zeVK7PN0zbA^ z@-@bYtTMU%Vq?oqxK#LM-f$gDzvy=o^;gI1z2-DZNE~^u^Ah5$&`hQwcX_z!^AkL{ zxOOImDzr>1{hnUypTE>cMbEm}q40G0S`(LH^>LYmmZ#<8)4hkx+GE>{1(_}O#J9nA z2j=mEvczgirzaPgp0fDWqAXBhVRPW;%RYWb+Wge2fH|i)s}5}sXTB2S3_B{534vTb z1llxsKIhp|;CL?2fZ$M~@yf0Dc+I;qwfj5(qaOyuEsz2mYkuEkACWhiIBN1*s&b3@ zu`CH5l>wn+duzTw#Y!W3q*t%|09sg=j6YK`reZ2fmB$|OA6OTEZa~&dx!7ZN6*c_8 zX7(~42RrDAwMJd@m`$=8+#MWXdj=o9a*|;oHE^Y6TXo*pmUT1^W|5`{m#@4HqZ#~q zA;8n^_^gpqO|R*RK(ZTq2CR7<9>l)1@vKro^Dy!Ry5pzdtnX{6C;z|Im{z;Lameih z7GIrpd%|+Y_+`lzUdF8n!vHL#o&T1gM+z;K+PIrX zI7$)aSBx^dB74t#gL3<&G6hj<`%&LAZ5S1_VHSioqpmBjVS@J2grz$2_H5m{ z%80kud#&g+H*b{b(3y@)S0z82ko>fA~V6iJ*-TaZx^g%wRN9mAYT;#4O0ERQ&@J%lT2;B~K$Cd%ycV7!c)sa(80AqG~Sk%RhwTFqb}AECS+bpP;0=>>{i z?^he2`W(Y>p61({den%m&y58DX^*Km(>6c=INNIkZ&Y|8TkiVJSeZ*pW-=n-R^5?s+^Z*k6zX zKy{CCRttqml*F-t9M>_Kr(7BU+eGFKJ+I%#337afvRBABS?0?lENI~&61Wt1?LlRF zC`y&I!6}!d7ZNZyoG+>k&@?eshLo(Y;*o8*ZXk@d<}c9O+p`)6=ca*Qy~P{nGNF{r z$!_;1upHGDXjLbOxF#zyx2La|WJK~#&`8C~qV_%8gFE*qIiNtf{n9!xhi7srIIod* z%!TIJJN63Vs;)QNfD4;m@AMX#(FACtVoT38-(bMa?^vT-mA zF3MyH?b)75e`;OGqUGQd(T@-e=&M(oz}sxsqDsKTI%w4HJ~uzuVO`bqbgSC)hi??K zDSly>f^B?EZ(C2M-g-YmPZ}Gu1T}f)hy5ol0Z#?nuPqkmAFr$kkvD@wY6s9I4cqHH zs4W;I#5Y&5Jh1;2M|)w{=*c0=rs)(UsK4!0&Fvw`JcNi$4>_^uB$cIrqssnfbB_c_ zeQC~(weUsYxuW@f00^?sEV*1W?+!xX47XyqT=7tLlw*L+_xnpixF9%g0dC$*?;QNX zzY-5lHk;K-e-K@0uZl4>5?(G4NJFm?o;JF%E;|bzmPj`hOp?6BQwbNvzN6E`q zV{?h%GUBY9kkRt!AcWd9EIrzvh}`p)*Ad{UU9qR*58q7L5XV*ioZy8Q;qeHEXNOeV zl|#n8KV}tt`V=Ermc*xf1@dnG`+;PvQN23Hl--du>E_R3!2>3;5X0W}napQ;WmkH6 zY1ATh8(ac~Ck+8f1ysn7hW%8#cOMB5lWiPSKoOA1bpe(iy+EUp{~j6-Zk!8)*1PWm z#%aV=jhdqyfre^4VO;$GB84<3WWd!jZ$Nx7q0bBl74@pSZ}$>@(gyogr0n8F{(%g` zHErZ|^Y0bcZ(4|iAipty<^>eB&Jb?3OcIv5oETXr8MCBOK}@owDI@DkD*I0j|9s=* z!)_a@eKlxWJU*v&ZU%!`+NJ6*RPF&`F3Zq!vV*L*xuhTs6mO4iv|84GJj+g9BtmaU zsuEFmey38slZQ93(%Qq8)2i{M_PCWIfvbEAYc;N$lYv)hj7umW{Jws$H;=$XzU zb;gV-!0=97`6DYPKZUY3$tVwC>ztkhd9D8O)>)YWYEB*YM zwZ46T0S1%G5!SDjf>T@KzCzrw&I-ZSPPz$59?J5D0sMbK1NNqlP-tnS=mEmu@(^3V za&4o>eXtu+CgUqT^Vw2Uiey2$;yK-rTIA$LqK6Qe4@dI*ykmRT(sf!?%8@gM~gSgP?RD&bfL_4ld{!94;F3yNE={ z=ABngxDs_xvRE`P<O@Tar z7sS3XU--ST-x$fQops!QaAMaFHH)golbA zXt^ETdf_DIIf4sRaJ4`B6^Ep~h}IfLeX8J%ZQudf7*0i@2!<=wu!`7cE7k(3$Nb#1 zVAQBi{}XZ~{=0@TD+g<+06V3r_w)9%|0O7C2QfvXl>NfMR{M0|3DnazDikMhVG1ou zC5N~@OVl101Xm8_E4KC|m5+8ju&gB?1er}_OFLeJs88*(a%O3?Z+0366$AH>%yn^g zdGcm}GYKJGA6cF$rLU13e5fa2*#VVWsw{A58S;4G7?bP7SN!G)!xtxs7IBqMI~dJf zuAqw8c8|P&CW9H4zNl3{V=R)r72&B$r-7E}iL(WC;hZelP9+{cC{SgwX649gDm=Ir z!rO0Uxn|j2GTpOta5Hgflm>Nbpvpk#$CxJqO09nMW2agwaW&k z!xABEu}NAhbP+@{_RM9*^|U7B+4x<*H4*L5>m;d8e75~n-tgRr;s`#|lz1!-)f<;< z*(nY#Zqfi;;T}(W^{{`vN&v#B`;Q(A1_-Jvl8|wTA3Z-97suURnhGNdzkV5(B^*8S z%nh~+Y&o^)FsK?g>P@LNFRpOpnfmQ4w-Mekdf2Pb0vMG?=jOj z)WgLHRREbsG9Fc>9)TEwv9$jNUX^hjRT;DpJ~&ksPcWl0P$CEt^p_knQ&10bA+QeH zUG@FXN>UEXGP4I)bKIo9fuE0vT8M5gB{{2=sq3vhX8KS(5Yp$IfsKJ;i7jSq|ECSpSDB-sz0Mp zqbU)nDKM@wNAm*&hVtSE4eA53@f$oQnOpF!)xSWTXq3G^i`--V+nIPL)Q3!I^bU{s zB%w)LfC;n$2QoDEU}iP5-Z=>-dxCw@qCD1bYfS)F)b`GPok4vJeX>(td(Jg;YX0A8 zC@@#*m`IK&y|X%oi#_oL2|Ew!XzKy=)-0(Sl(L7_>({lBK5hLc*&Ep|b01jb`xPU! z>UnNov(b7B2Mee|i<%!l4S+|ZVsWTheqBeb`p9*_of0vC`{X%m$d@z(PKgEapYIzQ zxNYTr2PbXxUbT-opl*X6SWD)Tqvtvtg+Af9w0C?mkID60ICh*6o}Gt)gFOM*(*Zuh4}96 z*gk}x+ZXsbd&96gZr&v;=$b74e1cnB&WEW!LVz6ZTZMK{^iG?jW^u8lPJok4?o@~O z9IS};2;>w>?KR{`nnm#^akJAFSDV=t(;)ROpg^HVL0NX)xvQTxcreV4`d6k%3SJ!} z>kvc5QqUb96KwWuXg%SHo%#o|B#%l;(bT=V-2uZq)e^_T#?^H?&>&Oj-n_H-h+F#3 z>s>7PtItoCI6Q+0xe^pO^wzn#`nb1kHTT;!$egyUu~BzZp+$OV7Op9UWW$**r|JPM zV4X>{_^BN{tFLzs*1_!d-aWBs;PJA*Vz-}OalA{lI_m_ipWY&3zB7cr90dQiQDN}4ROYwU#Z#@%)ed*@OP_dV_#8d|2>lU<0_=ts`y5FMypIr#ac&&UJ`L-qZp=K zOwZT0M_4n4`0pLQCfao0cqX!Anr6FZJT}{~($xQgZaWOxUJwP4nsXT0+fUDKX_=l; zWXED4O|pb-j}?P?@LT`c?2!)uE?7{bFIN^_x@w)XGsCi4Zmc6Fi2k5ruDr;TiNOFz ziSK*X13RUQk+!9(-A^1o>O^ZDTCRNC9~P3E9;?2)i)c9X1Yeo!di*t~;P2|``Fd22 zy2Ce&;ZKBQ((|6R1Oi$W;a1QCyI|H0el?2OgDb;&DNy?Q8`@q&H&#OC&}J0%e0bNr z^GDw8WYvLZYmP+3jM4;clo)d9ZtVk9tdNxtgEQL=9pmh7o|_ljHX}x+?-j5G74z76 zKaoFyG)(st+#}D(z8`300YMWr8FYPCuSGHBed)0u%rl2~93@wq2VT+MKFFTbTx7Se zcD~?O`M`%Zfi^Ynu)oFtzNGQ5)W)SV>xdiet@%v57k-s6XALBh=R1LXYkBM3u43gA zN+c2ZyN+Z+At}~WZ{4*YhLGt6BH<)X*O)l~Wp1B=>Am-@5sPVDREw1EJ?#La`{z@B zA8f8Bd0MLMI^btm9sKqBaR)*m$AXCM$NMCUSI#~N$F(6d%p#zIv>qtW?fBF7jr**| z*oU|<98bU%X7*{GPH0jgRhlXezw47SfWvDbQY4W5>f&tU!VWm#Nz9)UHT+E27x*JR z8Rz+c-W~O-=~tsYi7kepiLDC*Tl%d|9IRAUVUsJs(M#K*!1;#fWel+ESybCI-xb$O zzB8zt2plVpSyXo{KdNEnc}@B=mW8*E#Yv@`OGO;e1VV^UO8lh?_Lkzo1N_zkrt1)4 zfw*tdA2)u}1CI>y+-fonnXZ>fo2L_N6u@(HWHST$1(u@JBH%wNh|iiMAdLl_3fmdTzonGoc zL+@;|JI3nlyvQnxJm+SNy<6v&DX9X8`^$ANv`_s@-jIAtS&KtvA1ga&JeZlZlkzyu zuIL5b`_`bRJt><|`Qh2N8-ZhTcYC+J=%1qe{3aRQHh03|PgoMvj$@Si(Q@@SNU@Qv zO`mBIaJF{{hp&0tx*R^m@!nIs6uk)5uP;e>PHTXELvZjr;*-S#(~SHa7+`Vh#M^hJ z!s5y(oZiP%;u$!-w6`S66=qO6&+S$)gcf-n;FpN}zyOLU9zJ%*#iBwDz7c!~D3?~3 zDc&u8q~>GFw!7?ntOv=E(~J^A!)e;8$X?{SCmRdspZL@~Fw@iyO>Tnk1``ZLaEX>6 z&TPPT=5{@%@rj1Jt(fap^Nig9#+gf__H(Q^A_kyn$$W( z6%y~}f2Y;<);i~<8r#W{iwVy*2oAx7)h52t^TKD&$rUoI9A;(G!**&nyi^gnd-j!^y$82w5w;t8jBRt6*0>Nb~T>lwq zyer27vudegTkeIeQO@@e_-Xl9t_o05@msJoHFe`&<{J_Fhb2~I(05KU+O+J=+)X#p zjgyk0)&I7UZU5-KLEl!eX&&bg?z&^rg^QSXqf4muo+zHq#yokiiQ5==$&22zA8c;v z8Ikp>sKyQH*F|L3$@KaS#eWhip}2T4+van)60<*q6;6gHU3TE-UjQkN z&&=2_y&h%sj6)(gbjlj{RYAm&vKd#YV!zeIQ_Q`$r6I}8SM*x4a>1?-ss z1a4C0i*-vngf#j{m7lEx&{O=D?nK?Hn-TV36~Q=}^fj|O#7k$*IBHRA(j`c=3d3m! z2PYVOqUD#3zc0q&ts}dJ1-!P|gNw^}s)^Bo*NeQS4bp*k1e>RfApk1_1Aq z1F=OXb^+TsZE%`SemTXcJ5MpNL+8ONQHMh~l#uEZ3164eNEuC%W>=p)CM)&ghZsPV zMtT-&ag_z|#vt(qfiFes)uoq@LkW7l$ITk=mXEH+>qAYPL)ryTAkjozRlZf0WF8PQ ztn)iEwBXr?3$NrZU1zlmjI2K{G_m48jlg#CPIIS_rE(=&JN{cOm7YHY1dv`K<}EXz zd5TOl_-yukO~%bW*lh-7eUhbFG@1ah&&{28kOj=dGiHuTFmV*pK{`}#nOzNNx}7|C zzrc)0G_&Aao-d&-zUHz*>y2SPO~2nuFUH9>^JGg&orF3uBB0RfNt0rIJB5urFq%gF3G2lK6qPz zH*bHl^a~#Fc#+s+^>wpDq(%x3Mb@|&#iQVtWTLrYH5NDf)vY;KWK#|B(vAHwfDKQu>ry1^3*f?lGc&+rjfC2_;jfnW@w19M!aAllUCj}%CIQh z3aNJ&8LJgA&BZc(HwYf2%q~p^Lo|UK0!!Aao_!CmK8JK_VX7&;Z!BatlzFqUkXZ1< znbg&Dt{1UxUKQE0utO7PbiCR(iZ7%fl@d&5teEkLgcFv`S9k|x_z4zpll>9%sVcUF zZ@eCjKWQ7vZYrq&xhoniTra570<~k>_3Q+B_w-d|0aO*gql1u zJ}F{^M8~g&^luEda~&+JN#*}r2>hU0)B4mYvnnH3`j3ULDGZGsJDY5|^QDH;XIVwr zU6ORsPT&PbY$KSk6 zyPS>D%V(rrMcH|=a2EO#S1j+QccN$Xh6oKPNxCr=MYt#o0{Up6Jv#-ebWRY#BfU~v zhXT(6`rbAL>Hitg0!#BVuv zM`R#74ILNv7)>{}A3Pn18YBCw*{mgW&z=GvZ;6ZSXRjpKRWei|W!Kxoh1kmn*(Xn7 zu*U~QJjn)$0WV!h6;~t(Oyuu-V%m#XypSA)89vnSWs8Nq?NKA%euf;S&#|7M?ML|H zd!10_;jigl&u^VRp{8P(j)J#gT?nC0@37kl{2Ik2==YUCt2NNtQ;t$6YLNUIi~arL zsg4$B<%Vv=z8=t8y6`iK{^~H*yGVzB`#jN{hmvdWjc(6r~)$a zihpbhJ$qlY#P9L{Qde_$c>F;BCf+a2(j}k1t36D$_Q-2X)>OmygXBedv%``hj3{`W zVZQfS38My`9Xrn1?pw(TA*F>^K4J-AR_l=4Z<4fEHy)|${-zy#Xd`ruI^EuRy#;i@ z?J6jxa)$#_kmu1(gc$rK*4eZCqF7g3oHJvFW9Y(1Qm;n=@Q8$$KDOq2@-sK6+K$Hr zFPRQU?403m!_YEw%Y%HaE*|hJaqejOESKXWJFihpNg$luv%?loMQ=>}C=S^XMBKPnop|J?%O9!it^u8gEDXDTZ5*%lLc3khz|4w3n zbheKbhR_LzC`tf3K*Ya+gugleZ8zI6YO{EI1D@d1$Q@-ojRRgwIPS*S_0cdZ)--$Q zFjBm93dFGJY`hvO?oItO}TXZ-B{7s4D`r@Y$ByQk0PY0i{>f_A@S+Kn?3?iaWt9y3Y5uhZM29BRv=-hL6+zA~EC z3`pEtH8t`mrlhfjya7v#cU1jS-2FH-E#VLz!GNN0KD;`{su1>yIqgJv4n9s55ts(K zD2Mk|KpejRRl*-=jEt?%XHh4D$}G$<1RcpYhDN#>x&!GE4J{&!SuzIfu%Uc6m{wE1$?lw ztKX4kbaO46D+|04KYwb0Q)gYAIvx|brlj!BeTJvpLpU8e-yuWZqslNvmrWBT{k`>^ z0Hdxa?go6`Yb*4(mKR;o8)R!6JeaLG9KzHBQnOJuH{KHl0jVc2&EWBSxe>Dvkrxaz zHqLY@!J%fijOs^}h;pTOLyJjv{;~iG%x2f(ol9tZ_Km*SQ16SR&ywU=0a724#_rk^ zVpxe(2lMw_n0^J6+BkJoKk=(z|2g!3=u+WI!Qse?Ak12LB|OY?VgEU<`%3w9wKRdI z4nZT+iRN9x(*#bvq3Cv|>3JX8QyO(&m=FA&Dq->n97wS++BaEzIn2xUY+ww?{P7CL zIM3d{rX6Xg>}lLCns@uo1Tzes4ka9U|XiVH1Qo7XXc49ik^cn8TAjq!6!|6Uci3S^f8LZ~jm zHdylLVi1v%JuS4)sRWdI(s`rn?UU7`9+Zz}^LUV9#jz%prK0DGrvUiPyIr)dBd+$Dj$YXH2bawR|r6!8su5_|O`N4MvA0OaySRIILwy%8m zb!x@UN~E1JP)t3M*jpZ1a4Y^6=#g93E^&6vD$i$+wr3yD7FPnNbair6cnk!b`>2eK zY1Uy_qt0v0@-F!t{L5=kyT+n*Q0(xC&FUURm1N?Rh*4N=d{q@HNlu-i~WsQ%hUF zxmL^45OYJeFSe=Rss(M9erjZW@^hKJ9L%h%I{t@o7ZX}B`uq?6@u)kRT#{&PP%gj! z_1RtI`^RnLDCCx1S)aBXjzWp^=}xN@BwW7#p8|EGw7^X*7x3zCT@uN#nHw93UP-}- zA%|0YUa^V~_A(!-H;%KsmUgmD?=DL#n*r@jWEuUVWoH;agqU*e;s&t$nhVL%@& z-JvYu>q+1sPy!px2>9w|;0h7;g;g14OvBuU51V-0qJw1PqD&c|Cqv(*3V!WUry#9X zB2p9>4Tgz{oJS|(eDI=Labt)F?X#Y%V+se<4o)q2w+|e6PXrLREwTPRe}>bUbfCl2 zT4FF%cHZ*uc{FKo892f8F(d?(SXYth!fv46&{lYlcrT+bh6i$O-0HU|p)8^heM~WY zAKXEaRd%E(nqqylAP77-JdItki5AX_#lAo5)DL(&X~>Bc13=NAmHFcb z_;ck2m_TF{u^On?zUm0Cd(*7K(A=YLF>86%O~*rLkqv_L=dpB?Y`ehk7RI~~nlKOC z7jOWl02jK1*pSI0V)suNTBC(4x_- zh}wN(5t2qmgXhfREzUTN#msRE4m}qd`lMaF0vtr3a*W`W8XcIi=q}9f&A629C_SK5 zR}6wIu^{uBdvsfpQGl6vfidP`5gln~{U`5mnd6VSV?mzjc`u_`%uoan(0owuVP$zL z+-hb9ayNE`Z^QVstJc0-)#itd?1c(HNrHDUkt5DHHOjW@L70QuH=>HvwG_JZml@yb zjo8=^e)(>P0V*b#sZ;#1*0&)GBS$2Wa;*1IQ`#vEHkCM(hdUfbZuZJ-;855tTGSmC zUcP1jxTryeB{LG^k-_}#Fh%}=e&evRIyC9CV#r>cL~V7qD{)7GZA(VztYiiz#BZ=c zE5WPQFwlCRY4k;YFshu$ftjF!NY_A9;O2da|;8yvR@&t*~%%wHG0?F#)csb z6D^zdczKYV@wJ?IWUVeGRSFUmkA251SUm9k4wF&32=%T#KtSM%LY3jR%~J}CC5`oX zcIrc5DLz{VL6N8*4HjeQPDmBP0Yeex_1zUs49iuYPEnbFNfV@$Tb)E=eWLQgaF`|y zmnKcj3;5gdi`HpdEfeJgf^m1?js1@VZUYkxL=H$cnf&vz+GQ) z1M>$t{VL|80UQNE^kZc@s%3ERtrBKF2IL}a!>Rd0oG1eOfv*4zQsxbpxoHM*k0mTr zGVx*Kbd>khu7)$Nq-y1@8Ewa0jg*1=V?o6B*)%)egQVf`5%bavf*drb?SH%0p$;#} z=?Hpe=?MgaXZL2uGiOV9^HA~1Mt z+wj27;fyME^lRgABcW&DVDZ;5S6Js7QcnmRYF(dAQ63dUFX@ZkDB+z{|L+^7yj_UH z^1j(W>-}2|`@&*m%$eLsd$$_lba_Uwxtm>{5l{!Fc-zt%`GP(Sei-d;HrC`qEY)9* zO-4Yo4?nON)k8~yF}%v-vG0IrOXb=R5=VFEUZ(1Qg(-8C}|GaLWf!EX=N6XLP0d%wd-plJImp6C^20V2(dByhjfwI_RYh42`(e$E9SD;mLZ6-moE!iw)LAq?76C7{NQ zAW1J_!7bEl$;D*s?Ji^+z{-AR?6?q((8= zXN*l0e$8p)gVM*eY?6s^Ncd@>n`X-id*_tBzvFi%^S4d#ENfr>^`DvysEwQl!u%VV z+NIaB$E9B<4@&{u9CbfUZpMu$S!N;Js)wsi(1_}Z`(6Fq$JM_7l6b9uF?v;R3;_c9 zX7TAe0aqVn+1ec_h-UU2y^~*@z665%I1Ge^_d5KpuxGAT)4ks`Ih&NL5N<}@le_iQ zG7r;|ju*#e_MrPlkGMgU*>HQsBN&xQ4Y5qRB@zNnk4j(MU^9h45BjrjI-UofB)I=} zTa&!o);oXcO{_ge&U5H>M_+B2qpJvUu+`|5fF;R{Xc;fz3KFa;O9h0W9MuIUn#tCx zb#y5Q%&d1yE?w~(jdG2Ym3(95-=BfS_YB+c9pJ)nxo|%uxMVkLruac13Ctx|^#OD? zTl?_~zmH6Er!VKv zWoE#sMd=_5g!r zoN;1XJ?)n-Jf-O!>V5*BaR+Te6is7;HEy4ops;F%EAaM~)CAYuArQG+NvPp$mo%3= zD1ry+;kOb$uW#@y7S!O8)gBtlC{r}}^B0(ZpyN)}U_ECtZ+b|F+rJ^SZGIzbIMnp* z#ilvH-?5|AGc{$g!+glmGH9)GQE)G5wxw|V0-Zzf99zgKJpUV_BL=ue-eo+*m(%n| z(oj&tgy4X6Ix@otWfO}DclQX11L>hFx4U-UP0+N_;Ooj zn#vt10`1jeU}!yX*3xdsMm$7QnWBa<_{3}^tMX!*-g=cgTxOqJzCoAw#xeh_JtO}k z?E>ynaI>PguzhGdaF+@{H584du1A=H-YCJ<8i@Ho#~Fd@TS)XKV5|9CRBpu8CtbLo z&jl`YCyBP`yy;T?RrN3eDJOI_k0_sgOxJcm&qqvj0Q{^e_Yj!NV2zdp)Zhn$_>88d z?XOZZsXcrefOirrc<2dTO_Z(k!;;-|Uf`TD@vk;sdUcCd`2{|il9zQONugfP-t8>9 z3qSWDUi$2p7qfa1!ObTY8i3W-o;)nTVYI@_U1ANYs}|lR#pv=PS=so@0+rcpV&n;> z1|Cob{w&sj8rKxhtN@wK$TdOkEkX*x(sP$Tz|}WH!PaJ73ASZrkgGUpet50=?6bP` zw6B={-RkjAIDq&X4JOc25KqEJM}Lq85%C8@gdxb-bWII7S)iX?--|Ys_GRHZ1Bvh( z`?4weC<^0La0*`@t%3j3dS7f&e`cSlota7HOL{){Dto1^D~q##|%G15oR% zlTjy;e~8G%mAjc$0qB_B+LwNeXB6JD!rP@24?)8>7~|=u=pjDDG(9wm?Z$4$5*)I^4GQ5REkyX@%kw67E2$}XP#KBFYGQC z)ldzpC`A&x5ib3MigI`kW_4Wh0&CTbN<>e*u=}V1OqXy_7%d&C*b{DGf(%fdH!gx8?QSGjB@Blrtw0%V1eI`Ze;xtCNK-+*Nrv9QFQ0Uo4W1fXd~2E0G=! z|6#C%ua&*#v|;hdfK)#)(2gvIDdDtwLl-91X~<_Lm00l2Do?6p*UGTunH5VNkl}iX zltj)u1-CYN2&@wV0*_)CgNv5+yA`xV% zW{mNaqXHm*NT39@7N{5NQ7G1zn6}gfQ$=-dbPero$bL0C9J)qBWNLp9rhqSpK(32Y zQ$`MIM@yw5LgniRiv7O_+O1gN>v>V<>S7GYq|)EB{7~xOg2d@EV}b7wAQEAwlyTc2qCMKU~=CC9QyZ0pNIR+aS14jn7Q z`vDL@PK{;*>o3JkfWsibF30QnD%yKlm5L$FTVpXq!8e}ra`Sa%NMpN*#gz4uSYkz~ z8W8nw&0w@jqG}=uvbCQ30X>V1%uOBo#=Fyhk!*aV8)6o!tjbrz1zw{Rb1%b8^2VZC zeC#xZE-)uUt>xX7F7>-SFz;OV5=KpZ7CR`h01+ej=jj1~XugeigZc=S6404`LH6Q* zFEk=}*9b{ow%sD(CzD3URb$RP_@gd8omTwP1DchV!VyLvu;hY%a?)H<0j#X>VhJ1D zE_n=Gw5pPaYu2s#@ev=7kA>(}#Ks~V<8P04HC8V9J~{g_Nu3pas$R;FXOjCsjf^~! zh$3T(9LILzyFLT;^zss!00`jjk8$+83rT`Z{Mo$8uc0l`Lxz&p3L}6hG+fW5x_p)v zE?Abzc`?TtR`?Bqs^}$Gz*`a1VDk#*?t$XU4)TY6u}{j>lKx$%4Z2XJ0QDdFMrGxp7Gx)L(hsk-)Ss1av)S^bU90Z}6_aTs6B zc3)U@)a=MSSC)&FGD!R#VLYb_=7PslrR{?QtgLbH4}?db*HHPLg-JM11zT6hLM->0 zGYVR$cTFnR1-;j0E3&^HFohT&NvK~Qmz6NZabFGPn6CZfu}xP1nN_2X*pH0(9%M7F z+VX6iBr{5{NL`4^Q!p;j5%n)(+bl}D=c_MVo)#yX>jh57rc9*a67t!Hgp;AQ;JLtT z#{t%gM9gw&d?91WL{hY!JE7Hrg(9u(t#!ybjiF%PZfDq^ZT0lMV?{Q;EXE?e^fqZv z)im6@%EmT}(hlMZaawuf!u(F$#pv8vnrV)x>bxufHOw{(LY2hE-2>EQ>RlQy%y$q| zQt-8A>U{-Q>>oi+nC2GU@cR0cOexgIYGTbO6n9{)@#OA%Kj z#c1QmQRgSOg(i~mbt*2u2{&{8HI_ZPzbjVaED1X`6XUA*kZKG8du2hPVH)us0$Z8=VET~lAEnE}}f(r@1r|_*g z@OY-%a=qVP#=w5e@ZvVn?la;(L&sTv`;1o+rC(xh-xQ&j9e zlg_esouzS;fP_VA3M~;D4@$WbnP9e;78lqXDORSiGFrqXVFz@2xK5#VGfaSHNDD%Q z_|C^63Y5L2l!;KGlqg_vl&3*X5Q;nM&`h`r*O!sdWF`6};KfqXj@@?54IITE`d1U6 zN5<^t-yx<0+1R*py2PI5qDd7F28I%^ESZ;2 z&n#pLswG(NqqK;rL}Q{i&-&yd0v3xLaJJEif!l$uTVIMLQ7Ws?6`-)#XTI|&kUL52 zKjTZFGR6zT>t9aiGK(=yS|)0dBE7pexy5^T`2Kj@yd8tJ7^rPkwt6vR*5RS4YU&uR zK$6Isgs(SbbD;^UB02;}7GZW;nq4difLK1a^6~rjcoA(PCP#EL?25$i0b>;f0=41Tq><4O zom@=%-E;)5puvP>$f*mwK@7n?wfXb73!@oaPD<9aPgJe_-nDW?!Sz?)uGN}=2R=3* z002$8A>>LT--iGI8m{Ft_@Et?EaN+BsTKvzv!B}+O#cYEN(kZ&051A@Wq>XE%ySSU zzfi1%ROj>YG6eBR!Nti3=pw@c=S3B1plJ>a_rlQ6Jc&1&A28%voh~kt#NA5=e}-mp z7$&(p8;Zf9*C{2y?VQ5-${c4x6h<|r3enJSiW!r08nP0S!bIWJ9kfbmA}KYEg$#Q@ z33vl6eG$!DhU^voqOz52`$OxRwABQOgY}qiU|w99iV#`R7LyfkLM0oJQqoUqRxcO< z%Edac!9&aV9Q_5(5Y=J`O};xj!H~qy!oD}TeChr%-Fd#!ykzm+v}UEC5U1gf5H9B& z{RyhV;V_DahuZyxV=h^55{p+Fw@7KITrD->77U1;;ED{@hbm;W|t16Vq) zuHxZ7{eGq~6K`_jIS@7S7qHUdMkZb%yRw-*0S)cJ4(7DUbM%g}>(0-D*ztSvhRM!5 zucM|x#+4m8n9)zMBSmTJhD0)^K}UE{ia=44yh50jw>n%+yY8O#mgGEz68LIG{M#XX zGkptk>gbkwwKe>`(`b%3#uSx;i&k)vqVVOXPe7UuVq7piTvY;N@?Ow1l5n-$XOwflku3 zI6-OXovCyn>w)Y0D_AY=8cN906y%O(;|;jNHpMpY;QCsK0`AjwjAM zTh$}=2IDeliXSW*)#dUi#&B4-m}!#RmJPqnBKFj$;n~oC@8)O9&2{*94_p|1n48J# z?)wz_dUVXXf{?H%R{!XnEAgoK5iANJ>>37fvpY(PCM$x!I$ceVS+y}MPx%$0D?Xtk zg%l9DF85 zL=8}e2pKexrCzh;tM{IpB6knbSH`|#vK>FQ(ALbU$f`Atym4tamV(0E2Apd%Qbem~}m3oO%@x=8uSGX`8BWqRWCpKgcZWAS~;;nRWBy-|1 zJKuJfI}%rUFJn(N8yo#iFnk^Q_V}0X(pgDIz`t)_ffAJK>I= z70$Kvu>;XIMQtq&;NF+rGBuQ=9(W5x!E`Qjm}qE5-ZDB9t5=wM)n0&q`u%06&pf zVwqD_{?t_r%!wX<@M3@>+su)lHnQXWpBjJQ${RhfVVX543Jdi3;4M!p7QzEfuY!Qo z&gA?$Sf&kNXP+~thU0SH&SRg-9Q!w2ff)}bScQQFO8yfF$&LD|Oqlh^S}I-nUHf-K zM-Za^Ze>!sMmX4^>z49#Dk~3j0%t+xr}LPS8%fQuT%n>=jl50N4JYZ$WQVaXEsQ(O zXSK&UB76_r{4O&eNOnmF6?v@-(>n&u&%B!F?J>VFV?N0U8S}#M$5=jFzr#hnw5q89 zu!$ZI(?@01Ftg}7dN}k&GAL9|zdGwwy>Db10YU{B{?jKNy~XQ~tgYdQ?@3A%$DGd9 z)}KiyOpY!6^jcZc2yQQ5@dtB;0E<%*xe72`O(b=sMNt7f)_TIRfBDEb zj(nZ2v>ouiD$|{DvkYtfcCN*{WKZ4tW@DdOySVDoZT|8dG|Ka= zINOn7Iu*scbbK9?Y2dt6X38URbXh_YD;k-G2zpp;KH}PgP4sMYc?3p09MvDSpzD>A zr2907*-SRd**&c9H$m`r0*V{c*PW`k}#Vi5i%Y}UuZTlW@nwSm z`uqxEbBF_+J~jajzrwuCOQ`DMi1@Hso0|9Td!xw{krV1jwFpZzfYUtubwL;_ElgZA z>Foz8y|liE`APm(%l}p7Bx{v&21UYt%aX@afxdI(l!p{efFbueR?7AJ*(70HqCF8R zGKx}VdQC30@+Tf2Wqn44o|80u**9*BuUL&x>J6)=m_hvl8(UI@OJa>s^L6LB2z(3N zIC(^gY>0>JE{O(giL|slDclenH#>Dc{!72qR$@)(XQaGunAnbX6$f0ESHXTqF#`m) z1Do;@vYwck<0;$6=x$EZeGVn1ug!MxfPIPLmFQacf{K@NVN-_6a;7GgpF$^eSzIfE zFdX(2LMv)C25#5HdrYSwX47Iqptsj|0o2|b3-G;xg+6lp1~oHLfizYIqr?$ zJ(m*1dEgR;mzb=9?QyU2%e(ZaO@np`E3P}3KC-c(ev_N8!F3+@uDSgJu$=)#(E>wU zBmgyxHY2Uu@MtHjUz_26kBWYw`wUaR&_StxU_+AzK_;cIH1AjMP1*NdRf<> z&QrtU39g9e@^!O}K#~*rs>NZgSQJQk$UVY)T#lNu9XnaTaH}0#;%iG;_mNAR z3^Sn|UA&uWb+SftNW^H?5X-N7Rw5R-sW~XRF!&ZdKlLr9ixWr$r@2EJ427pn#>q*8 z;MY8y-?Qvprnm-k&9^bjs(RtRF1LH`Yx$2G6=@|iBiu6`(Q=fO(hC7Iqes1-Wt7)h zaLSQ6FwC)?Du(K;%5&UiS3mN)qw!XvqrV<+Q2i8_wVPNJ^2{8;q|F`#P|F8WLWF|MPLHg{X_mpg8ZkG zoYD&0d5dmt%XcmdpTwG9_7vu)=D332BCo2qDXB-@MUm|<=Gz9DUavm)6%cX&o{;DR zVD;1dwk1+~wN6HY>W6vF8@^x#}%d~ETFbcy-s9Oo)u~i^_ z>Bdol*6OW|pfFG}#I#7K#Fn}fh+lt^qCISX_fI-;Pl&H4n6bp<$ADfrT5%9O;x%{> z$>{ang_CQ3BAJpWX9)9hcoSO9>uf7g4I;BXR$%aO36Mcv64>kbFtv8nPH$AGdev;? z;ulJ|Y_oYnxiSVJ7TX>jmDL+UFDD^U-vD#+ovW$_xmBs>i~s_@3c^o%ktTCK-RaOO zlLYYsvXzWVDni7$9@c@M@IW@}B50<6ogOj;2Ywd2+7u%|z@M8dEd$@fzCxSH_o}`U zdEWgg{X}Bkg~8|^zilW5DI^6O%uge`?w|Bnm*>PCCvkW9!l*&^THbo>6@|$oy4!DI z_X3V}lmiD9&`nN14z8u{PyG88R8$rbi%xS2*H546OQL~H9%ZU+41BIt-vtvtVmuH0d*bVZv;b0DM+3{k=VN6HRy9Qr*Dj-?m2E$5f7R z=3|E9j6<|^+q%6^0tlC+uPHtX@<2$;V%$ zY2Rc1*;{`!ctjz2zosJ~mKD*G48<;*h&HXSM)!B26j^osX?q=jGe3E|w z{p+Vt$Zaxd!+Fb0L~o3L8={YV+7hhJQp;-Ee2nech*u8XsNwxC?mx}(O$R3Ib?Man z@0{YQWM8~(!mmj5Etmmf9ZwwVfY|vgO2oez74jJ zJc&MdX;nw$38n6o!T!|955M$$=)4g;hh_!@%HC;f?Fqk|I6845VOrGnFeUL7gEPmV zDHIC6WuD(Jy0)VMkl}0zT7#hu_W|)kk68q#sVp8Q1@7wD2rN%%Z^=y7Qu}N?-yB{l z_(vcLCaxbb0Q~zhUC5MA<$GIrN}&PJ&Zs;=Wcy3B4Ot~piEc-!0MxL*w3 z{2U`HZE0BG-<_enJcdq5N5!I2#)JabByEF)hHZt_clw=7vo?;4XdCk_q)HlJLQAXD zgo26;w90B)(F0>OSP~QRwHCF5Sb2L>edd|69Ddk!@WBgE?W@f<7iNHru_ekN&JOe% zX6(HW>)2YY9b{6P3{Y4|ZIz=6ZhCr70s+zH0w{j0TiD~`d}%Y7NMYcklfs{d4`uF5 zhmefcK-C?i@hUnhW47MFZ{!mDro%nw(OmoFnQ#WFYo7>}^dlY_^-Ki736m-}QIO7-K_r0q>Q42x^lJz>#Y0S#3t}+OL2pV%0H_fz}6G zkS|GGfH;JBT_uIbKs*Ck33TmkJc|h&%IoK$I7CrFKI}TYTUII@ptjsi0Whvk6;UmO z)7j!LF3o(nB(?7J_1?0{lQmgvJyqkKI$UCOv~hBf9vCf_)<#yXB7janG8{-{Avjy; zem~ksV5=7l!x)6(bU(6XJ``?CQ!OwHy|)6meeQk8l+ai)je^@K5vjFD zZv_aayKVT7vrB3}#D|aFT=6DM>cuetcHnNOQ_@o1~TOG&8R*RqHI1%%@;^p1q=RwynsC|e+v zw1;2Fz8deRa8vZQz4Ii~re;+b#txn5LPu2uqsj5(W2*AEr6mh!eqm6|XEQlQx)f;r zr1k44k^{{08CSE%qt7#!7~!sl1`=@5pq>OI<6DAssZyJX_5yvl-OMxsjY!b6F8NaA zt$#IBt&Fh(s8Ii>p=vP?{?q8d3OwO?Yv7i|I0h}JvNbueE+N(Fq5%#6#%`hxsM?&T zl+b)RLaTB{rnw*|!B8Ehp)w)SlxU(qv@Tfm1YDQ>G~f=&La#0}^bHhZ~L`h8W# zx_n?V>_T*@9c@$pdr=h$6+g?$l6Bp(y)<+)-XW zuuld!AwW2Rj%%SVP@_jOkl--iil8O#EMM6}(TqfspsoW@N_<^0zXBwLiE=`~J#Ba_ zvdI?WA;?jf4xGuJ4M`j-pq@RjjG{XECF0Q#NP*!C9K}{IsgUF6-jQ!Oz~2{c2p$jM z1d}E|o80C?CmqlVusIpaqEu^Fm> zRE*TtJEG?M2qE86d_+M?8@~ISOK)Q~1097bfGb$@-_$z)A$6odmWNN~nm6}H&ZNyG zQEOwB%#_y~m~R6N=}*PGLapr3=5Qg0B`97m(K?47d<(%IL2e{2p zhF(=dU467LtB8F_(cGh`a1CdiXA69{r}eNGO*}GMb$uexvRr_*QZwOWC0ktJQ7jt; ziN0Swq2KjlPK{VtYyrTEet#J`TH^T~>`MUasF%Rl@%bh}Fp)>6j9Krb_@KN7nX272 zlThPG<}ZeMlXBccJAuh19MJw~E)m$@AdMlHP4^=LjJ})>O6YaF~ zJwA>YRWw$gJXdD{HNhNg)C-jb@a4vKkWTrb$MS-z0SKCQAr|bQJ(GI;wCy|8{S75O z!P><>e&u;97cz}413fVFiot=jFt6RDeNlHx{_j8LBH;z;GEn03+9Icp4WSurCJp+h z{tRp|S?K(SH9EG^w*e^qSKO_@aD&%KtF*0ox<)y}kPAT`2thd%*tK1IbHA8H`n`}Y zlv5d4NI5P-1PY2a8mHj>_!x}P_JN9eeKogRf=Wg3x8#}V(=~vsT{rGOnZBd){V-PY zS!^!bJ*B3=RhZwXH<-J)(NI)&*Qx|f5K{_Rmb0H1L}5~G4LAP!*)UYNtZ%ovPM(sGpLd4nQ42zS zzq#^hkiJK|xB^1^W|bqJ`ev@JPiwC%C{w)vPZ%emD;=M_+`Lsv+Tew8HQfey{m%c)kh(+F>2tV7vSzAuYsOBUobu$}iGmHWcp)F8-Fx zBVsp{zRb}0s@=$C+A&43@5uazXFSwz$w(?tq*49<%>Odm{iCzRCqxT__%r^R`ZXph z@V0wj{ey^#2+U5G4_PtQ`T{nkiQm_yYFBi`BC3o&<}yoBCc@6rFU+hc?EW8-6OPh$ z;@|R$HD*7Pm=zT#jmouH3i_2vdHmzT7Q}Zm&s*IB17BeKmzc2xS|S%SjZ5v#K7q2t z0(o4w@nrOo+ic~~e&@Tjkw2h);9R7q)brPu1oFyZZf2N)q^%Xj>uXBFZtLZ)M;k( z+`IcGjYiVr4tgbIvTSD+MEdO#yr{%lb!*eecTKpt?hPBpiUYC}MQInF13K(EXlZj_9qmlTVaH2D~@yT8~H)dSz@7%3>L*h!Y@1M+wrx_R> z&*_{|MlOGR_2;Oz%f$@FI+IyngqcH1+2>&`wTf*e+E>ncdYesk~vuAP64P) z$#4JC!SjeDm~ZS&!1SO_-=ibxuZXf84650`LIa#Gj3Q(HG@`!<=Do;X`bz>~3;vVy zS=o@91>#3l6$S_9cB_@=e+U#^)1b4L**v7L5(u<`HrmLnqT5^Pj|mdKc{ zCLuP7rNa__d7yt}j|@b*j5OdDN^gIbzMhy5SpEn+#Y*!D^QM`YOEL(p4FZ^`B2A#2 ztD(wJefesqOc~#da_tN4sUo)$MUrD}-FSgQb3CB@()_%yD z?D;JkCZrg&vqmbuH>Lopymy^ zTN{fCO+H)#@%~$-iI~xXqP(yh=&I(pevAe-cn`4t#dtr8Bw*zLOHgcf(C+Q^qJ%)O z%x!I=cQ{FCmgbN5wxjJYzasWkZpbyF0{A|ogB;>-luv|fXU%-tjlhrXr|Hep9{&hu zfhiO9zn(3kehI?8?BXpmNfhHZm5~CW>c68~#ga<=1%do=nWE>$W9@(26#pCn7O|e+ z=h_WVfOGpzPN6}(n@0DJYJXT!!%%t8IR0Dwch;3*Tiyj$cKaNk&k5*9S%?E`hd7Pe zA1PL{VuM-U-rO(pXyD@M1x)qVgE1L9S*g0g5|VY?@pFNeEM|nZ>hV^P+^cwk*Bh@% zGTMfaRZZIS)mSd2DM!ImEf8i~gs!ohnh&&lsr#U;yGi2O%>&~*-enJbZ$Au|B~TdJ8X^5M<1 zE>GsY3F-!4vjzo25hOw3?q=ic>ij+LdCH3sZm4L$PPt$GzI|A{^6N;aiGYQAA88Pb9}nk zUVd1Ys)sY#qG!0_jG5Sh72_c~s$roE#VH9?O~}G-o!yX`@?Jqs&`WmpPgs;c>=;Ri z`}Pn+O};0EXw?Hj)C`v`drr#($hE7f$hKM>PQ>Ucy|G799BplSO}#0J@ujk2cNK}4 zS!c3Jx7Z4tqTF+{-Ubt48Tb9^EFJB8>R@V*NtYvbUf17195-@HA^v_Q+j7S)i!eyR z;dWE#1|(wG6(7uc#`ro|&v*p_#N1BZBIb#=&q6JUbQ#aI*hJGS%GK^A*y1~dP;d~T zPJ}`$eYcd$X!vj4dNBf-Zh+W!dfI)_0xa`BupZcEs-Y+>??#W8NiXXBQs95mE}y;! zR3?M~Ji@!3&$W3=uFc+%uY ziSDs3irR1`D#cP4q|kvZzOO`kd=&zDjLnb0ny}EX_4wC1u3YE&WiM(BwmnQ)xl}X3 zKRdiS+-u+z6rizz)e`^0wb@CN@EV-VaX8BbI@-aw)-Vz>pww+9K?Ii%Y1O`_L!@@@ z5q-gK;J}ZON?lGi2spiBoo1(aWJZ~J+^-#wD4=b!#^|26=3e_M(0Nh9|vC(g<stYRD?^OEa2`= zYXOMMc=lfoQkk6didA*9){s78bU}FV%jhxI5IF2DqgM-ZB-d}hYct@%&!g4ppEV2# zCp^iCp3?i4M+P+aJ%qNa*DwNOvnJH(gFD&`!CK|3+rwp@f|Aob%e)LR5&}-9Xv|uT zK1g=tgdQl&%IRrZXEqek_jIPFj3h9h#}0MCR+HZ?&@p}G_MH#4j6o?Dxi(|aHAaoj z<80HC&2}vM``z$L5=r5}DXyLs+zDOcnT&B`i2&5{pFg)Iu9{VL<07;3Zc-x^? zZ92ptTP0Ot`FeAq8xD}asKs~0EQh>qYuUe3&ZX&pJUKZ&FQT)CF4Nzew6|7B<#E#( z-j|lz##hL60lWU?y&8;419Nz!E5U#{{oGP= zDXCfUjKYOL)#uhW`)0oKPRXm!{hI=&lu&u)1RL=-1VWlVN<7$nhYh6G?HH5fCG8IsCw_?{ z&fFvm*hyKF=KorVROsB-CI(|C1VTpvJnWJR(YEl@lLc!1KK~Ult3~7S3ezx|L$%z| z;w;Ro1}~oq(nPhU5M^jX+yhH3eZdrAUQP#|<&>*sToRVckW)-DNhRctSw??w=#O!g z75+0W=uW4Rp-hA8ijak0NASFTgxE)4+XdjwPP#hAa%z3=xX>xzF&roo?tFAQa~7nC zu04)%$LIEqFdD1U&7(<@{WY)M@~cl<}?lhRv#g;I4^*` zps6N&;E;H*(z$)1($T@M9NdHLMuCbK<>o>ugq*eNilKa0;0HL(nWq8XQ<30YN}W{S z16kUL&#A+~Wit2qKvJqa*j`D83aqMGo5=XN9CkEyc(~Kc-y+}qM=6f4bk^)UWfxRb zLru2qoVgm>cQ~i31ZodzZ@Uk%`oqqUQ3mJj%PLk?qaovg)5u~U)=if`XPJ(tkvzbF zuz?3n2h5X+obCOJCKVwO?Kw zyQF%0+CFnRjc;k#AJS@U60LPme`?v{Kd%@YkKHFITu-?MQQW%a^L);|)L3axLF31B zOds5_D($_>ic^0cJfF|c8co5(_mF@JV`OTsA4POc!b}j-y z#}2P|$b^6n*pgFA>H2bn-GCox_txE>_}v<_dM_g+w1QVn;={Nw{h`2V_Zv!ELB7{9 z!2z=a^kjH1qvyEo205B7O&e5jW;YmUj(T_AU?J>GQU#H?sx`U^RNr>A%s}X=t2{+3 zhHeUE+zG^<@1DPTe&@^z<0BleT8*OFan8s+QO=mZ(MEmcxjoOwK+c|z!w$MaImlbW zA{4v+O=|xDad51AZATG(f!;NencuS8qQanVB@A4a&Obu}j}OQ|(GE#J8jjC5ON_u+ zvX_?r`mw24z-1X!^99h$OCNweO-t|FL(6+A?q~k_)aG8J?MBBoWA;r}CU!w)Luqjm zAr}(&L)^9_2d@jUQzEAx#uw_&VrYyAWmHuwNL@a;=6B zit~kVF4m#>%DfF!;TB0U*w;!S*MuPp`t0tH5QT(~(l?N#ssZtoK8HWHZ_G_mbbx>u z)xMvHLU3nU$)J^s*kx69KDeF58V2AAGWp-){E@eKMZlLGCNS1yBrvJQ#l;928uwe` z(3tLD>|HZ+wm0f5?S$#%U`eM$`?xuTf1Vw=)cV3!Vq#ehb?eQltj|MA9)h8%*9m`> z0aEZh;*WF!S%QvtnACbKRr+MB1S!OMRQR!nbYHeI;X#atF<~ut(T;bodOcF;xvNL( z2^7p>(gVAR^b4yH(xxchZ3E^s`-#{crnihbY$ z3}GVshgJ1l4_)yu;R$xpmUF-Fxkfc!#Z;s2Q27cGo;8iJDI)(0wxG}w`d!P6&gH`o zL1aJ<1NR`y_{t7?YKZvI#er4Z7$Wu>r_5`lEJGB3gH@OMurbTz7lxR!f+OVXhTn^L2LNfdnNrVBdW&4=J?JLIwTZu zkl%T{84P$1DvCYZ3ZSAPAxt%E9)?!Pr@1vv7$P0S$p%zFokrSScLJK#W+r*-dpgqw z3mW8BI`GY#gJSz!)dT{j88o)va^D5)Q(~3`57Ex^&5!o zvWh~KHmFYxKYW&Q$uhPRw*_L2{#Ts>OXAM-#_$#rFIM zTaa9L^2B*|j3JA7uWSm@@X}sO6xi4vE1uZJdy&`9H!K~#AkXMBJ6j%UAd(;MojG$- zS=Nu+d{~0(IPScfSp)iZ7p+z;T8)p{@MX}6XgEv0C!ftK_MMshiV2XPaL9P?pZl1<};y5baLghbE) z@u|v1#TaG^*1+AZdl)!?h^upi6G3vdc1en=OyJ+Snz zpbSVAr(X7(3?u`o{OU5r@Kbm=zo!KMgxUw{FdKc(pkplZ&3LZACMe*Zv7a7c}f zwv2`uocgpFA&{O!9@MAd%>}5w?*;&NM2)0!DPHc6p9bXMAN_F)lJ4@xbswB*(12D3 zgaby2av>b+7Vd1%s{f^gdIn}Hg2_|;O9iU0E}^oOdPo@#2qg(LUEV9tfv|&|*7jgr z*z@sVc=#lO#hSA~D``)32%s^*T8ytRF(G(sIW7em!CmYPFVu#wuV=;cb_O=67wQH! zEE3Yi*7x;H2T0O3mvCz{xrpyAXONg&&1_QXriR{#i1DGpl5Ab0yQQhggNtSId9Q%=Ex z{vDU1jycs zX19U9cK|jeO-f}YKbU1YqFqgsug%KQKN=IdFt1b*cCos>( zcBP()lqB}hd^=IwiJ_0KS-46zcqo1SfJ+Jcqb44O@AGg zP8S!5R|Xx~K1NDXxIcpapBhQ{RF{M;Zky1dz~$^p5{c^xjq2*M| z90n3$k}-#Kc-`En6jhbg`3-I6f9G2NDe&jJC^S7B;KL ztsrQkPt%pP`|$@+`TUlKrMZgx5tPc8AaBaWhaKr(b2kD~huv57e>j$0y5UO0GL$F^ zf?pD0Uj!usR!KzkSaxLqBiYXkkamC{wS2S8=6R_KVZ3%_ZkMsiN3h4$Sh}|2sKp%4Dtu&hkaZ0K3Vpza?yT-SK)LpjF?-&Hz9muZaeLR) zwcph5lRTlx+y!i!1x{yp(m_`UTM;YD)7HN<7@r9!PG!`aXY7ft*uT6@b+YjIiZ>5V z-7)68)gr?a#DwOBD||GimL6wMO-_H`2wYM)VDkeuxo0)31?mnI11s2l0X);UO`A#y zSBJW0_tQ19i2`~XJGjuZ#D1!e=^6-(?^}FL3_>d4)528Me+K*_*JW1A@ioHs?+evX zzz=TEuU$ptR7>{(+oY82OS-^@FS21EzUBcdPL@D#@K2gD*koJgL*VvLAiGzLUo75J z>k(F*=qD~&)fcCT9k6^#XiK`e`4adbq4w&`OPXYIGE42<9xqJImoAP=&{gAskISQE zcGpYpis0i8ZW;r+9HG1j0i&73`r2)UsRSiL`70QGFs+<=0Vpp($f|*XeknZ0dDf+CmGf{aY<6&mtc;ST-!(DK)4*B4G%~(Q`x06&+v4%BbuhaJFprmQP!(!k|9? zJ#mbRh~>@^ipo7`zzKQqNuBbaQa)c21-QC6rQvl7ugcQPG|s1@edh(L5f5P-SV`) zfy?~Jz1%420u)ai8UAah&LBqLQkFPP^Z?rU_pT=Ek-qbmA#Fea1AKo_q5;5;-pUyR zGF09k6gil>xc1iGx{DM!dvO#M%`}GGwn2MTnM@2j!G9=+LcKO#?4R=kEeP=42`o>v z;sE_h*stA-KeW*v7-KT&jjRo%ZLb}`VXQL3`n<+i#hZ{Fw~%*bY1c`>7ym#*NO5p0 zKtsfXyZvrHUlC~65DZANcGD>g#j3g@?>wb*1*wq4j4z#2FG9sbbnC6be^3J!x;mAd z|3Ju6n&Nl;VGv^0$QmYucn8TC$=`PU4jet22=c`e)mE4C@gE^8#Fi5DLdmSInyidi zl&&4d8gE`JKQK6sV#Y!HQi=JWX!O;~iG$yo7o7suJNBUZvh zT!iq4_|k=y^1qRwhLcJz2>G|b4TLw&+-q;i=M8ZD$CM+dUV)mZ{0IG}7+3v82s?2` zMf&Q}n*C7+Pvcyi{%jSK7lHm9TzpzF8MCy+xIfTzby+1{Cy!YepNn(VGhvjWvF#R; zQ}ZjQf~!J$IE^0Bq3LQ*73wZtxbeJF*Aw z($`{}?kRb63oSH=+X0;SaJ z%BD-vJKxZ03~m$b{+g*TC2|k3$EAbVrf-_QbZ0ch>Bs!q0b!HU;W8 zebksd;D-Yl)dtHpx2h~;&Hud;p=?Oi0}sC+PkJIE-lLWxLXWpSHewBC7`g;pGWDFOw`TJ><2OU52RrI!jFV97G6C; zj}_Fy77KORwKb_1aoV-KbmnHeZaGe|cEV3>EI32Y*yyz2V~&6hz-#Q0I8gB|y0vwY zl0)zPEI6Our=MwIehNQV;r@0NLFJ&%F`aAz4w`Qb+J0Xkd1tvclY(ovvG{$m%^ZIF zqOe8-l#(H+9H=w-#4s_Sb_lbr5~S-?6ZbU8qcwk+pQr-XR4xka>sZHWOAP0QA>Rps zF`>WLFR8treDN>|N;-Nx=jd*Qh6&W706Qy)pDeikeIUDr3=_IK(48Tc{JE7RSriYl zU23`HqCpJ#B|sc!y}X5{Psg#!>mjcU`FgxP7!<)wUIiJzEXC^w96hN~z9 zGzt;AJ)8{6!?p|QmN>fvl^=UdZ5mFgBy`=I-U$pdOic*fnh{vZ{G*H*G&Y9=*kHWx zhUlkUCsByFPZfovg|`4nHKij(X{p-8BPH3oJPA7uKX9^AN5oA!eZ`Gh_~tuY<4 zwwTy`gfyvhoMkmY1z33GE^17O5fVt`a584cPw;=aQ5gE3;NxTz%obo%wf(3+g;QUtWgRTyV+Z+%-Ks+A+j|OWV(yAxhTwP7c4`@g>HUk2H6bD z&E@MxfK`m)MPij#9=9YbmsD6YF{X1|-O4vnG1Neq$3fU0nWbOg!r{GX&|pUBquJzCE@WV)6{{cXtFsV-J3 zdVcRS?}lPikNEunqp^B-&jY;@4xULHcK=gUbV>l=eL^vWY_hPYJ`v0r*V2OV*?yDJ_1cr=oj+vIgOg$NsCc_0E zK8`4Xe0k7|CbZT5t0^95SeYUrugf7XM!{E zzD!N=LaeZxM3PH`O_O}wh-AZw9XA5#nmy0RGGN^dX|@#7(YGb`1_0)LmfGcoWo6#L z@Ja!DU-)M3obZ|+A!9dXd$$?p|1xpHb?>W1QC$xq)3=F+=%%pajJoDY zF+Vy$anw6Hkwm@?fgr!hbiLc&w#ZBE?Q>9j`6`#e=4~S|y#}8H9*~edM9j21zJzlb zL^XIWM#HoQudwP&k}jc$114?34mUUo@hfIzrK<#HWd1MtT^|yLNnORJE&dRTYK63t z0N*EF^QazAspPMxFA?)uANio+2*GbcVDf{CUEhE^IHb) zz{H1~G=9%Eex|RR7&RKG5KFBR0W=4^={(R%2&|@2E7)+g!Y(c$un+s2P=1y? z3NDX`dQ=A`jd4x6dJAY+$Q+2Kb*q&7rd^3eg zh}H%YBuN)so1vJ6&^Cr<5yN(IvpRacc-2INGXpFTUNs%P8Z$r{?Srg|&k<~Ob`qI9 zN~qhYh_Z)UVgl$6!;T?L10yqEQ%|genCu`euEq;ABtC`o9D&^-CJq1PZ5)3bfrYHP zh;#lzdus2$PR&WUYOLRfb$ralGzrU}RX2IF;4hh|%WfOF!M_t<_`G1ENDwQ8OXj{e z+&dt$Nj=5#5m8>PST!ZmJ^muQ2J7;bD{`=GcPL~E7Rev$E5@h&Ml)5^{Vl4&Fx0r& zgo7jQAGjDbQpg%vDVg1mxB5q@m50CZ=mN{Svkhj`y5x(TFxgA}^n4$KRJUJcq@6aX zIDT?ErYjoM-98@vF`YUW zCeu;^SNM+&2e+0pupdZ?#k(>Ek`*BdrOTBIHV*OU?-%)p&)Z=M4yLg>F^ul^o;pVx zUYE0fa}w6@aRNh^LJLPhh9NhmiGz$mkr^E)XD<2F$Tu1v$Zr?vi0hV|NnXa85rm0y zL52i3S4CKtYWlHy7wb0BVS+=Z{C3l{^-lSv1V|4DyUg)qd#{lWj#HEm+z-I=C^@0W zA=xH7KIe=pRq-jhcOo}A)2bId;?ik}{bcv}D}M=u3j5!!1B$buVjIc}@8F0aD`e8GN!6xW$y?x!Oje+d@XVQ0XmLMYQKXNh1l55g zhFR>3!Ys48tSGs$Ty>4?0Sy1MG0>_l;sR#z5&ldkz0MHXGlve9u+~CrcP&QHVjo1% zsc~YLCQlhP5kLLMqfxdd)t}ADWCm#ek+sSit)iwj+qU(MJMHKXb$&L)Qr+ful?>Q5 zSooJGtg>{)Hv~|MMY*wn2V!aoYqiriiLpr%x-C`jGG9>uBQ^gzL9-n>De8~bcf?z~ zU(OMkQ5zRF+^q0)Tpe(+w3%K~W1#J6YuRx>(cp|H^?LUff*7t+a<*_v5}i%$H7u@N!7)J3e1*a=XZang)R9Q@({p;R%Mh#jekc)EZFEWy+v^U@cL(dBd z=Uumx9;J_iCDnDucI6BB-L+_*boX@-81)7)w`@+G5#QLSxd-txm7zs1_T5>H9l9@g zTR$*EIt5^~6n{KXAru%Yj_YU@?N4BZv63I<0MYHti&)^J?Ua=HFYV`%aCEj0z(+ub z|K?8AIn5NN^yJ?V5Ocy&Fv+@H(&->d$Ra50jEpyCFe>>j_o|0oW#Yssv@jwzj@VL6 zJGT~Cwz3F(uG6aJ12L&W{&9T<-D7+$29k3jivtenL|fvNM^LqJ-ujIlH{-Kkm82i% zJ6{$^|1Xy&x$#K$ODa z)CbiMK@I`>?OTAhILCbUpyXSm+UsWHId->DpI$Ld7k+XT{0=@>Nx6tT0PY+u7MbuU z8H*>)u&+Vw%@YJGIRmEz*4>!rK%h>+C(8>%v^IDzq_MAM!8R*MVr=NUmD2c_{{+`M zn>U1jYb?3(noSBA^YB`A(^MtOIBd@oDqru78lY{O&Bln%)&ElMTk*$H{1IVXj#y7v z>xmLd1*Zo^od!7ZmO<_Ju30U4MwvpdJ_!RW2?jgE_i#9Ti}~&CE@(yxtd~JwdrWvI zoj`#0M7MrMs_T}pbR((m>b$A_uN_}$498F>J))( zRG%;$^+AMBDUF&M%#b^l(#N9Qrkq?pp)k4vpv8Q>@=-mWN4{Aa71 zwOZn`gV$E{YcWGI*Wa37|NlauFGsK!@Cz;$)+Ao;^@q^Bw~rc_^82cW-;PR_?(8i6 zhd4>rT(vf<{ay!lVZ6GykMGjD)#sI0GQgQdes>lm*0YDz?J?;n<_v`^G`?i+I*$%f z_xkiz=@LeDr|Ff`y4Lb({z-|5gmxFTCfTKH+^Ujths7JI!yeOCH7^~;qd)AbUF`r( zAmYQGzU#G0-6exN)t>iTrt78YCv)}aTC%lr2Chjdq6QRp1rCZVn5`9=sr5*go7G0@G5DY+cXD=&M$X!?KSd(_36= zQW*;)dY~e*RvKemk_M?GXmtM!{i$j!!;t^Z6dT3zsG1+-(4%Bz>Ph*5mbp3kj`CRI z`iev*$!xmJwDj{gV-yQ?WRcO6>D%>qns|wB#09A zQ5V}35SIR~)ALBUprm~InFK%$Nu$JiMZQL}c*P7#=CO0hC-=(K{v;w9s^?|1xWT(g z=^^IVC(8B@-tcjs)aw4?nQiSIZ1p4mYE5<*Zt{NJ;7CFWtVQx17B!0f^MgMf%%(@^ z?nv8&p0Dc3z8BSxb)!CJ(&qa^QA&lzc|ZFtLDg zQH=Z#P@s?2y8d@=Oo^z6hix4OW$^e06&!+3s+&*%^K8^b7aO`OB#=E~Mba3vA`(6& zWhsZ9S;rUck}n)GWT7i%x>!Ezv#_7%eVv~rb8uqqaaKfNj;5hNGyp#Dk-zsNZ?_B@bcPs1gUU$jO$+u=kTo<_n*tP+^k>Q(6Y~jPV zh|YO28+I}Y+MwcFkTGW!nFUrBFOu~mu0eq>F&o%(eyOJNexXIf+Hzk5Uu`r>O9rvX zp|6hA-~h?Oh%fjiTP-2iLS&@s41yj?ai~Rj$R!6ErQ!^j1T+40|5@B8lM~1+85auN z{L#xB^Q_TWsvH)th9JHPK!)%;fga_3o%aV>(>YuF>8WX)T=d#ibEvWJ^!kF8;QrM2 z2V&S$MnxH7s1=$zlEV1ODJ0}G(yk>Eo(ScVg z_thXq_teIRh#mXqQ>B9~@;RJBrw3$R=8`w!{ZO)iN72NW2eWX+-aa$bg}onmjTftH zcQpVe-w5|xPrIjA6bm(A+Mygyj;60@$<`lzsiUvdBQ2N+<3v`F3&Q@#762(z3cQUS zP|orR5c1`-YM~RDkSYR7ey5wG2rC>buJ4vRNy)?*0C5+HvA}0@u-p$yqS|+Jr&FuM z<(AOYC-Xe>RyQSu3`{YRjNu~*pfoK*o{)!rU^w?G0}a=y61D!C#N(VC19IGz6>8nI zb*3=CP|k9c0gz7ulE7&D))0HCv>kUv<${+5V>?kZhFoPlK;#JlGrCLCV3AiqYW9f* zVen0+A&4M<)Q^3P7|JP%KWMt#i0CP*tR@!fIku|uatS7>ESvBHXmcS7l%=VPgd`}4 zicuf{3YM@Vo*)#o1a5Nz8m$bOk&_95!o*g+vx=2RGXCVP#6)v??>JoZ1tY?z3&aaI z&cZ32g7$WeXG6)fpa=QNHt~;U+$?<9AZ$7OFmNF&G4tYY&+zN;3RV#nmb)a!ABwl@ z^;k~^q1@b`rHu$RBr>qUimq0mb#+61)ve9XIn>K*OqiU5bu^z{!X~qYZHv;Tt9d~a zu{CEL&&$`>43?+Px((>yOWeC;VVR9zHKrx)3{)`{L_$!J%)p_~v<`YKQ;tz!%e=wR z^h}PiuvlITXE6anjLp463ds@N_-9fH+5snl+UWgG8BOD)hr+g_XjoSFc5T|E&cKRM zwRUB6o@hlJlQlnudHjIYQc_r_zyJO_%-F<)%$H7Mq6cqSRKIJH4sIuG^aUV1X>+MF!ehac0!4i*IUmrIBsc_J9-ELwouHV5DO$Q zRiV)zf(82(sl-wMRepdq(lzkeOnal%?efNHEiEFqshPq>)b?CiunkX34h)W3dv~95 z29bw)r$N^$;(F;HyqP@zULv-$v}~VCy<@>(lHP1V^9}H*1~DeUmJ#KKY)h}As4r{HorAMY zSOCuFc}?GJV{B``b0=9_2>~Ogrr7~>l~N(z_t`n{4cQ9HcO%Y4M8WgxH*0vSLOW!( z-emKk^y1mV2P0Wb9NuWJU*<$44nzLM5wsugyf-ZhaF9F~#ZtViE}wzYShJ>K1sv05 z&|L(@3Sq3ofKf??<1dC_4)qLwC4LktH?2?fuV71CyA=)-T?%m7yUYHXW z5bbY2NXj=_D(Okz%S!T19#|R!g7?|thxZ1f1L8z1uSyupey}F13cW_?0iV7`_z_$T zZ~uQ*KNqhzlyiDoc(Obdwg6GO1U!@_b=?gTM zFJ%gq2|QBuRjPif8&NgtBU_> z&_=IRDz4qMLD&Fqb3J2ntyh}-gG+;HBGHHlz$uclS0MXc3t8?JMXo7Q^!{f;TB8rT9#%>$}e0fb* zTRH}4)Ns9A1To|>ufrRGS-I!0>-AWYJ$f(Th3zk9`m_t#Sz@lDmHgPCruhE^OJ}s5 zF!Hm_Q$c)E5tFum3q6@!8Y6!0>1)pqwRh}2_n~eP0L#B4+8!1QYMk4ue_x}ahRsP? z)3+MapWvkq_a?JI~~{kB#WB;U_R)l-1eD)Q62ato zrWvEQMcC;81j=X4kvnT0vFFTe_1p1+u8fwo0QRbr-1+-GysCH|>w*>+I9Hxm0LCps zF04$rBf+uAZ}kYG{Eik!ZKew^i^Za2EcP6UaS5e_xE(;*WxY@mZWIX(svE>ivIdgM z>QH}-WYvQAkFx6ms7BSy^ztHI_ zt0c++hRjkOilCs=pXdKLWS-S&n_6~q0AGMp&%rjeRo@XII+&?NW#!s#P`5x8xb*}d zMu%Q5{AXw3$ms~o%$WJRWXMh6=2cN|iL^4ThBMiu7-w6*C5rd4*3EK;eae#E#}Rv* zQXNG4U_gVWQwn)QTsS4m9QT-6uQLX&%hJd?q->i$Es0(2J7g$U_Hl^!m++YN251Lv^Qx`7mIqo>$mZko6mcKZ4uGAt8>cudQ;e3v7nB;$Y_)mXgsS zZeTyO_6)_DQI)sXnuIp({h=vypvD$!YJR#v(dS~T?WKnPqw#)N30<}FmrD03mjAg$ex=QoE^r zrm+BPZ=+2+i2uZt-n!>Ct}A9rsgQ>%i)J*V*;y3%R8TIh6&_6r^A{AcNBe)5ps(^w zhz8R}vc!{4-k8_5BLru zIwz3_4h(>U7M^)|B!2L?w*)S4oVk|7mBsB3A`T_&?P;}pXxx8if!J?h0|5aeqVike zg?rR~+MOn2(};RU><#{I#o1ps06YGMFp9>@75xi1RSJ=yb6?Q&Lp^SDXNYn~mbJL6 z&cQb)*3ZN-U<#e29|yAz_0hTfu5b3AGk-cj?LHT1Iqot7BciSVB*>V4;1@eNHVi}# zR^H@+kT!l^h$(D5bMI-!nuL%xIi`Ix&>q`+17GZVNK09po;H%PygoSc9}a~Ih-|_h zVZ^EG?nkq;HZ+Qi{HnL71?`cq1+*D26Yf3ZJ=y&2`2;eHPkaC*R*cVl(+f{mUqrWr z6pOlZ0sLt1lCN(_VzJ5ZRqa_r711In@FeSw0ix zQn+I8tM8!7%m|WTj_=!g+S8wg$w9CKRPo~Z?f??~IUaoR2>EyBVA}}ass3y|i`FDU zq1IIg9hkQQ4NX*~)q!8pyzS}tCq$jtFH!blkwnvZjS$rbl4XXe(sK;AyVjL(umLpo zJM|zd-7IZ@@ryT zLRT3V+(!fd(HmL2!lnr-O7i!{`>w)f1j`x{&*(&?djH%-!Ut&wG^2s|6@^n7bf784 zL=d-1)>44u!0TixUbodR_!N0iLmWGhc~qd-eI~bfjYU)=gR)=STfBt;)Bn^4=a!tl zC3orHz;MyK-6{g4-rXDR;G9g|muelu9$?5V>ug3HyGfkQKj59pD$UvJykuq+2bMXAg4|N2gZg`--gt)X&l-(yHInnLIX)ne ztZ&V+pUSiBi7$@ULe>~j6Ed32zqm#1(_#t4EZ(iy0|z582ORuQ19OqI48~t*H)C6s!bV9*sVecVlLsg_qqvUNPC=L0 zWt`8AT#Fp9ZA1Y`u&z$aDtBktLG3O~H#zHDv9VsN%?N4sDZ>dvUx&mVF!v)Y*~)Af zsj=$bhebuk=L9VrN^{`awfTW!iQr~OKbIp@(irPp-Q0`DyaMuxIANR$oSBhiTq9UfR5SjTmB z+yOqti*(>wIsghmO4RU+Hf><~3BICQckbh~iU1?8Z>glNrQV>u52*?5YVS@HvyAKF zy;AJ-=JydhGtvatCQtF>2Q=MD+5o|rr6FsQ5VPdAkC2+iIEgwzR@mtbAd-3T#@2!B z2^3=lG3(lrlvhX;eY9ycYsK&{?uh_E+1z*yKFMk7Xz^~&bg7l?%Li*pQPK!YM#f_B zV*fxkESuBY&V4KiE*Ck+8#*$QPW4|eJwxMr%M-2k#>QO0wW>?}6A<54xw0HqLpl8F z`@=Am`&2@YcS~}Cw-SLsLIjK(f-Jpak(gZ5WC#>gW9eJL?}Kar+Sj!o>w{E)K}tf* ztZM2kRBP&5OmGE}iS`b(wJR0MDiiqlTTS;~19O*U&eK!V4V!CIQNeS+ z+y8++2{>%H6DLk-t?IWvQe5 z*kbM!ZgYIgF}}^6hIb_gxIaiE6AM05;l}^PmSq--3lBO5$#WMZ5EJLVRb|?4IrH|>=O4FD{;a%qEd;jLlVo>|~Cq0Rb zL@TEN;kSMD0&r{BV%f$*ERnhuVs{|guOj4YtCFY z$26au9cHId0{ndanJW!9;BiZwCSor>@T=vQl=nhJ{&05FG&(cj!2fxfvMUJxQL;R8 z&G#WyK=7v6;5)RU3*s=>WySZ2JM;bZ4p52S%ZZZesB|LmeB~E2DHO^>Q3(OD0L~f}WoHorv{28MI`1AwqmDM1 zjw4Toum1Z(kHu@fJ0C9zOOco`uY!c=sRfWCsl03(M^ul-?m=YK>?V zN(>5~&baI8elhy1i-ZNuaD<000Yt0jZD8{{RJ66%N-Z%GT3_&~bnh z@c?X{yE*FwBVkI-fB**7Sa&dr0JXxBk-iilrE-o)kmAV-cv{!7TtW39e8U8?_P^_+ zwk>#>ioA;@GU{)wh;vk~?j}qij3^@xJl&B&-0@Z-xog)FmV#A0AtJT$Hek~kw7lc4 zIQv--=U-vn)9w=imG(n!`^p!Z2M;HwUIGBOA(UXq++q(N-IwS8p~TzA3~xCWxA4Vd z4_|D}Oi}|&BSLH}En6!&fj{vyhJQDg{aUD33y@a?0noV0cf@SR1aBwA?4Z|tEDkrr znTbT6W?|cl5PJpRVLLA;0(q}!g+2ku((-v(zWdd?J>PeHD5kMd@dlgz8W#Y$`KpQ+ z_+6efyfv9Dx2hKz>+yq0^IRr;gN898&-3pw`;m4H1Y8Mr{QQ#q9)b?oAI%A1v_pTl z12-$UbYdBrMmKnRA(77g8G7@c?|Mj;Dpzqj0>@e0Gs{Gg8i13jw$S)w%j6n%Tc?52 zD7T$J#dcqP{DL-w`Y4Kh)A$rBF++_dvxreQwFtF$sH(w!&%?*|-%TOQG@@Sow?QdhK6K zoclLO>CkNoksSuZU(M0P$A6|x_f1foGdr-%vfM6ou00)e_Nv1ipIS0a_C1QByMA_m zzo~|25C4yZj~}x5QCT~&zn^@!!}n+sgEBKXq!#Z_+}+U#txt%0!o2Y6BNtlq7sTr0 zSaDqY5mI~iYf~L{hdi#cKo3n${qN@WV4VIQL{kO1xk{|!WCZNsl&1ErY7PzHjU}U(12LkCaMVfqfA24F7P*?!k?b;hEio) zh-*{uwdJ><$>(oT@WncPq}W4Wc`KMAw#Cgdj@yTFec#BKJZ*vZ9=jLQ$g>P9lN4lS zXLPdn1V@gTQLgsB$lzXgZYngZ>H~w843}|=(hupd6$u^8PAHk0 z%V4zA?)?7L!P)6~e>yfW3P>$(7MuhE9PiyS^jV_kphoP>_Yrs`2k*#G@~ozl`>??> zSh?y*g>(L^`Q+T6hXE9ducr+y7nI7e_uan(V^-4}*xmb!9MKl^S zdX^VlKlxh1_l88#+rFmAJ9lDUE`PAdB8ju++xP9JRus#(cIrQE-42`{XlPbrwup%K zI{opLQZx##XnPaIatu&iVN+p%=dkm>SboFSHJCtaGKtjCnrdHmfI^?JF74#G;9UBN zt7aKh`Z3&fp^#}u2pb1iS6GH`D283`b=h(VYu28Tf`P zn!#JZ&cwlopN52@40xetU2*k^bN=xabMX;@E15Nf!90?HLNCkv2kEmb7&_XP#D3W6 z@upoNo9zD5qqYm{%nz7ItJ?n#rHhTM&T)0uyw>>w^k6i$ z>=?r6nF|2B;%Gh*G>MMacuB?dF9OD{+5PNLJejZG=-^Yz_NGlm&4C-##U@Zj zQnsLKf-Q0S85gkX zR09$51=|F7SS;$vUk349}}E8INLb&)acmtpx$bGqXdN!%1aHIm*ug@-3+F z6lOt<9h%?b1L9qMUQ#YBunokyDr1)G&ri)SlgA*h>cFq(=I3N&Mqj8C(OMy#q5-8c zY?cMNIh+)3s!n={iRtYO3QOo0MmS_jyuK`B`EC!o8mQ4d#Ms}=`}O&}m}<3S4#G=G zqa6hwe~U<%lIwi$3AC>7&0XIl(~ct(E3xy@yp1jYzVqYlA*~%ST zzJky~F+E5zJ(~Vm(A;iqT>9eY#j4pm42{Y3{71alf+@gGu>l>rcT8VpSXckdU@4d$ zS};DGI$f&gPXJ07=lJ6|h9~)X(dL}g{)Ofy#2WW_su3;(LY}%vnJADH=3J##GRGFE zH)5oC|A;U2Y31}#nX9SQCharLi?`?Ry)Uc+@6X-k{S(`9*dXxCot#@mr4hTI7E))Xyts295ZJ~#Nj~jvcDLpW8oBZ^}LB^Yl(I~Py z&uaa8z>@9ESV%?G!6hPBVh_wfRvl&Y$x7J0^$CCqXzJn05(Roj%Q)WdaUp@G1cExT zR_!RX8HTH9rfS@b{roEhdNJou;otK)MGc#ZH{JP1=iynxPp+isuop`kAfMs<8O9Ho zNpBhOi?I6641~|?@{&K22&g~tyhCIXxG-&Yhv@*d32j8GU-(n@FSlGpqpm&2Z50M5 zTQ!fFixJoGv1_;_s6o}ZP+5zPT{QCmjCC5|qME@y-y2>O`YoF-y%xq9t|fv{b&dv3 z=dY*Nrd7Q^@gQ#>8c}IAs?#7+uXOw-uOMbBSt%u~ZJf-^0$3fT8-u1idx!9z*-p{> zW(Bin4HF5q#AwxB8lo?HTHqPEc}%Vt<($R!z}T!lvS!O;_iU)rSK$A$R<)){mp+8R zb~VSruFDOlP>shL-itv@QRc*_3OgnLj{Vd)AyZXxmIEcoV(k37MfdOvYFoP#O2D1A zx@JsAH9m4mkZ)spQ%N2m#h8VIxUK{~zt(b(-j_yHtWZ?~ffXHVPtt4gUqn}k%Zu>= zDwFwH9;1+0Hx)wgI_>^>zb z^3k2uJSbCL%-Wf9O&6d4Udf+8I-!!=c=g_Z=?U1jfp zDmese(<2b%6nY2|gH0sZG^A-!(vpd@YTg*pA++w-J_Zi+T|Vh+mE7g44lpASNN17C z$2p1q9-jI0t*|lxgw~rrrn?xWN&7dTP*Q6TA~8oKCLV+BXws{|8-inw74#|AlvbYEHPF|I!!2rwn! zrI&r=*N#>uawQydfP)FkA`ZmKFp^LrgDBGwwTJ{4iD2JG4?Lun8@Kht@&KH`P}zfj z45sp~D9Ttd21+6U3NZFH zkLQ2vyN0m1(JmP81R>7~cxYMBr*e0`tNSeJuWa-d<)yd4-3f^+!#SK&`Mw!ugc)Ob zv{#chNa%>5u&W0l3Y6WYCZa;9$bqV=;DxG70bTi!W#d#Fc9|M@B4DF}3sk~VNoymT zAm?lE`tq`e68ht4`FE?y{TC_ezpQ(WA=?7zhUwH!;^L!_JBYUb?r+$t^@1KrN0V`& zB`NTAEudMD$~AF%3U#0w`C=9OHYPK8t{Ai;OlEtQV~E4`^I0;t@v|R1h`W;@b1sk! zKJ^^T3}X77@gHkCgHd4_mXQj_3e4X34spCMKMTLJU3X9`Bo$p44n|sE;!82eU=k90 zg$<;jq#_{VGlM_`fN!G*EKTQ>6M#1}fS@zd9LdGn0lzH${u!;qmhUR{uLHO# z-Ncrc`woYkMt?+%>FKOR8$D3GMQy!w)g^TmDL~Yki`clkj*o8QuENNra;~fN{_AK3 zH6KgKIJ3O*S>H1mB9{=6XO!*U&8-1WTOC_P0Iq_`^o&w_F{vthsC^^*hKAP;zN(s>PM^<%a~Dqj-Ify<^yT++;$MeY8oUdo|Lz_g zl};0i7tIWv*tf>v2&gAz7+M8C%^Z7M2yG(UGMGpHGJn>@S!9m^DXm4^?t@HStx|o0 zL46oxVy3<19N&`K zml)tBp%0axQ)8d{xPJc0+Fzv+`AHJTdz`)(iItx>VoWAGp2=fLfxB`^_G%TB^`D6Qk2*b6IAqX9_mn>#-( zl5vN69ceKY_L-bp{G+0vi(`SWFyj*p!uEgHjUJnkgh92>@80Tei`EzQ*Q5|S>3=(t zo6_MYwuUr*u#Ds_qyB3_8MW^LV`9sJoaq|^CO#jSyU{1lt(A<Z`B3BmV6>(+sG6N}m5<_ChZNW1&nTzTu{9FKv38UoPA{8{OYFsc-Y zTNks~E^}Rx&Rw-ucp6t+EZU?9SbqqUUeq8k;f%XkxbRc+IVkE~bEUfI{4ECZlJz?-A1iso z1a)$EQw0A+bKxBBzB4FCLLvT>Uv!R1CJQ!vliDPEw6fKh!5Mur6nXlXnFR8=kruop)?6!=*0J zQp>#A0ZSl^Vv@)`(aM|#zSShPr>9PYrkJDC-3a}g2(8YTlzk!01Sd)MB{f{A7DO%2 zd8lR`5{d_5?c1azHGwv{VkQV74UjnGO(Fq03fxt1bb@mCDQd zBqlG>o|`hoAwl+8Vx6@Dw7RY6Lv-d~7rr8-hlTxaVo9&-L5udjx0pLNRyFPSn6_jI z$7+#->iJyyxm?l-4cId>Mc%z#7t*1nA?IZ>iB6kAVgS4x#+?7%HUWbWyEV^A6X(I> zXImMnP>pRPMYq3auaNN49--%62@NfW0W|<|9XD`Bls-hlp)7j4D&OkTcawuCqFgLEfX-rGvQ7MYpeHRI+qU z+c5ST&)33IIlE_wVnNq{cN=e2#ZV~Olp3(n$N{+jkuaxGK0J$rYzl4O+QZTB^=Y}q z%hk(4S^6{qj=!FysV(Cbz0p4MIdVI%X?zdN*I)EFnOgzF8S*%7pnsoG(I}H(&EX0t4yBW0)nIUlSq%XS449Y0*HPqYl_*+5<;;C;J}2Q3(u+;UDpu zEdYgpD9CfxRGWBF8Y(&<-GROB`*4Ducqi&!|@@*ww7y8*bHwhMgAAoYM zlsdOt;3+Q4pLHNG+rs4gU*_$fP;V*E%7O$bwwyLM`Cb&L+MvEf&tVYz3M2;Vi(~<7 zeIr--y5)%ZWA8N=%f<23l8kfoIEB3^n1-(|C81y({{~{SIRa?ddV$nbn6rd(d)}xG$c5B` zbse@=W1VZ+6A^!6^-wiOmA`stG6IGX^NFShV1g%>ULR9H6`V1gWUPx1%HYqpdG#sPFbPyqq3c1UslX^W%@&zC7 z8EMMewyV8L{HJJ+EhN8S)Q0eM?iJ}^9`ZJz&oho|3+IC!Jyx*l&7^YsIS7U@b;1{F zc%Nf%d0LS?i*XS~I^BNKfHF24&mC4W{=T#YX(s7{)CAy}H5zHGcXr8osMVR(W38Ha z6{FP#^FGAtgxjfRIq-sO*G4GR8mZ@htbiHFtcuqbPZ5$W5}YTsqvdTR9F)!O34&bI z)m!vai0xLWF{9L5o!-X-$^HuTis$PiQ75o~=~6HfWvXd5bm!RjA&j@7A9184BE8eI z6dFkkN!~0vbU-#*k9G=r!Yv-~!QnUM-Rq+kz1y!I=0#d>o?8Cg07CFLIHm;GQOnn_ zY<6;S2He(T3Fw9P+a$ZzZrXm)CxxpT-OUv!UB4fxO>kT-BdJ` zEy|)fH`8S9=VwW5*ytl=PGI`+2$d+n)K4=wH9dY4y<;93ynOV+K*d4teVkS~hsXwK zlDJKIs)y|lOtoxAYJk(C2@T*p!$rt{20~wB)>eF`mtkq#<;7xvjC38l?=XtM*Ip87 zuLN(2f7@BL5V4ZzfH$shs|>};!sb9ZP?1wYtd;d)<(UdC9o&OwQ(8qFq_C!_a_D1N+=bct8>LPqzBjW32$TsM#zK53dw`EXq4NKNWj z-+vtW@DQq-1ga=T|Z&e16eKEc34z(a`DR8IIZ^lm4YRReE5CLot2y-rA zpObmJKfqPfb<_Nll-jH*yA~cf(UlLuL{WIIjXR!>0s>xBF)Dx?bXM#J4Km_NxW2l* z?;+1Hn}%H(#QswGhoN-J$w?E`X;F6gdh$eA02Fn&!|wiU?lhR0E{zjj5X9%!vEv}E zuP4fKkj)QZ?b(9!M45)(ar4io-<_}d9A-BY19RU34BR`W@AV$owm~lcv_{hj5lU36 zA%~`0K%L@&I+t)j=1&@&RUMR@p(AFZh-~m%nh|69Tm?7*Sz>x@=pI~~G0Ff}xhDhU zsEXZ-m8}=mbFYSnWHN@_09ARFk&j48aFAExNwKFPny~(|=TlIiwHB z6}7)SWX6PXA~3Y|ZMM%%iXUQ+20RKG(|9g@5ppJ6=m2p zfUaiMNm7Wb#j8!moxr-YSFR2Y;UrFsJ*LQ_jIv>Hp4*wY_O<_ly*3jZ`?tt~g3Nka)#%xO<~%iDk|myBXK3za0USn}ruc2i?Youo_ud~*?% z%EU**i#s;iS<%blGv*vC5+_MgT2?FmZZY{9m>649k1b0UnMhnmtuQptr&H42WASId z<``;(yjf>jNGMiU`V8#=l~R(FGOWSh7Ub&Tp?IreWdd=4je=afkY*uP0m@MIenbU2 zE>~WYBy-UA3E!m=Q(>JL7i5u^T||{%eJbW+$LEtxQ4W$>9kSB4Ttp|HqCMOA;aAj$ z@{GfDPqnUX_)30eDo|?ODCty-Jq?5rUc~*`H1iiE@N=3!8h^u74i?apgTn|bPCte` zf9c<%%Y*3o3k+XrrkOrvHnu7m00qP2H^Hwc1 zK~9wyFva^)A*`?s?iosb!mdK^k@SiRYQVUQ3no77->1<{u*Ipu!+$0%#x3z#M>+C6%D0jilO2WR8u}c=^m3jnq z_yz-}Cex<9VT!h6xk&}&l}%ZRx|iQ9j8SSLkE`)xc<#6)=n8hHKkisWs~&ye>ckq- zcPOuH{A1pS>bG7QFnihLzlA=kuDzGuf_(lk`+uyRLUIxoPo#;=?#YENfvc+kQT~Lq zaDl#+`yaa8^yqQV82dgza!3F$C{$5p)^-Uq2PUo{so4_HLsJ!a*t?LcX^w#sW`5RiIKLl0ei$1R%x_tZ6X`c=63bd!i}I zt=dYluiSuO3O5%gEwBIUJx0GQcEAiRcL2)fQ)4{>qV;iLdC*^qnS5GvX{62&7qiO$ z4YS5QJxk|0W*m8oo}=eNH}y}K+T!oJo@`gZxc@xAp%b^ZFlHN!=|IZ^-iI@*#~NPFU>I&6bqAq63yf2w13;CMN!YwpZ(ot6p*hDx2> zgTeBVs>!Sw()JfJ6l_bcUGMNMBD}LjsRhr0+i~rw>0za4MedI;HnD7MFpDo(i87>4 zHYa276j7Z%ihmvo%t;NtVcY%GVMLq*9JQb?QjASl6GK)z>HWpQWNi)baHstD)2m;8 zoK|oB5-Ky)Q15?5TUU+wv)^bo0@Wx3$ST=Al@Z`VDK=ksF`-e1X%xT*Rh#p8sj`(! z+}}m0ULh@cx#102vy2PU8_s-MH=aT|EZCmwG7(=XyRD1hmAmjkGV+)pVZJ-YuZPO|hqal;mZPuuI0Pr`>QYY0~~ zM?r`8b07WT>6`0OtHoAsf`nBM1HSs{RKd-OWgg1PZbse)`=}x<)%5$I0^RHiJv+?s z3Wh^oV9=M&Nn<+2c&SQ-Rmpf}NMa70KSSMUOS1f-2aPlNxdva*T?Hu~vFfEcIlSEF zmFJ!CQ)Rl8hU@sURk+g0STQ6(1iysr2us!U(a(mujw`VVphow-C&?!3B6;iw%Br)6 z|43nJde6|%KDdSvfFmr%X^UW5pjY!#`>d#*?}h8R5H*42Yl$C4MivVnp=IVt-P~vV z?kv7=YOYL2LaSui#L1~Vznnk>>rk+4CONBFZI{Y_sLJsO2Pc#Otm4&G7D)NExpnZX4^83#PEtJ z?fPQ4LAj2ZKQZ%f#gz7h7CJ}Us!z4cfdqCcURbum-4{_#P|z23>xT7z8u_b^a$WGxnk=9q23I>xBv<%X$OY_6=H0fv?hm1E z3C_M}pp*^`-x0!e^1M>Yy;^MKPT#s#Gw|I#_9X7feFe=&E!Q#+Bcf<=a{0<#I2g*YYX$EfJ~GQi z4UA!BoRwnhK&KP+|Gv-8rbRQxf^5xBT2Gl%jVU7i; z^LnOyOGy1h8V&-MznP${*XZ~|K${mWt=fJX01hDc75#Wxl2gcg&^IUMSQyc+v8~7f zJ}8Ys`3CtTXsMULcf(P2I7NHGE~(t3oT}4+K4EfHy|a#$#7Ki;XJ7NuTxbi1l7d-? z0yk@p|FQKa>ENfPIH(GE09T;uWIl+6(C@x|Q4oo@mYEQ_(8h;x?=$is%g2#%yo?p4 zmiBtfJW!OQ${an;!ve5K&}Bo2PDEZ^?jv~fJs>HsM2(5cGZP@d7FE=yW6tjGjRtM* zY08@DG%@OEYrPhP>L|%sgx%}JNtq+H2#N+BUGw{_v1l_f5J?{Jdg(zZLk|_7n;;fE zbG|NLm{yBtfi8?5%@Keeamc$HemuNcji>u)d@h`zj5fET@p~Gd?!ZZM6$Tkr7g4l< z-|WwJm$b@7oVvlV&viCxxHmcQlRh)H>Ed9YZNjm%6jcVfJySw`3h>!HtuF_TBX0wT=^LWtk3yA zpFR$$Z+WI-54*78ji8You*?T-{l7a=?|$Ew8$XX6?weQ>KyuQF65sN2Vu?w_xB*9v z1;_ghhCfw<8)WWZ=Dlmm+%ndfAsIbMQsWjyQMaktEC|1%j!WOaf7LHHF0hWhYCUmJ zJg94;sj)T5L`g=T2=VW>0)sl7h)>C(s{@bM?(J^Ro#M zd~Y)YG#pU(0j88ffXk6}Mrhw&%slg`i3bO$0iFKn?$LR%@Jk;2Ob#*#yJulG`bZ>1 zg4-V3KU=O3WsdC5k;qx3t`(e%rxS6X?!o}1cR{`jS;*K()|m;ot}Hg%d&6?*q>3z; zXCH2zaDKaWM%x#NC>FH*qN1wu89VMI&aH5$-Xf6E+l#d)mx6Wl4q*zoqq}jzh+%%? ziucn;%^%Rjm5FfCxLHsi{x$@0Jgh~}L&tHJpYiD{ zRy=zPRRsfSCteP1KwX{pU=#vPHSt#0t|{J-q;Tc%>b(mvUs~9!pvXvCw|X8Q;S^s? zB)|>1l-fC|Xv&q>(0k6+VIoJ?bA7w>x0z4=UcwCP@JYnu<$G&p06Y4o6lEXHjtgu) zAD7bUVX$jx!0-z8IV>n4m^hwjb;$(mpEoOg@Tj3OMx|J+152!YLihM9xH?XNx&$BU zI9&NAp5W@nP(XZDmG6&L$YWAa3q_r*bQ=LyqifEescT zUseL{YHS|Ixm+S=K%NCX5PA8!70Ml0DP%;(5|IK5(xul}PuQUwNXJ1>4sQQrs+nYl zEB(`uy@Kt)ZK(sVX8lpyEzgU~wfySL%i#@J3Z1+pYDURA9JkUpdlY2;tyMPL;JD!#Nqo@rcM&ZF~f&x9^6%jHp9ejrMuGv}6lAa`l6)kPzqEhuj7A)drn2P5@hu zxnw)`thklOcvkGGxW&7)zZD!!HgcBD(x7dtxNXHv%)n{^Q4e5CW+fD^5k*f-P%d|W zw*}CE3hUPl1I61msPv+U7nYiTBi%%?P_NdQ1oGcGI%>PD8eb}=s)!=7uk(w z_cysg<&Rcx>os3wMaLq-m0FVJIn_-kfnWO(=KjfpU_Izv84V8WZZny*d-n zQ7@#XERLvkAEk)QB?V=R40M;TM@r`btN_rImDSfxEj;Voc-v5-um5%3Vb3_{4z|iM zPS?7N88=3Di0%S2cdprNM{p8Xq<=T55%io^M|5>r{4t8PYLW6XmV_x^f0;}nDhHgr z3U}S%8=QxQ5MVFacC%l|f+G*d6czrSnnceHt+09x7!L)|RM0V3Hnm}?tgiml2Q@O@ z_>v70)twze^ixYlD0eoB7im5$=AL{xBlf;ONO%TNpjm0Y?MvR9oqlO?lvw)WB4xaA z3GqvTbq{RKh+K_i-|I{D6dAWCV2;l=6zh{m(FVk(c8Z4IM^*F~8)sp{0(UVuUD4`t^JX zY}!c9$Mzx=CP;Q?C!T3-rV|XZAO0n19{^vAjcy05nsi(c5(*AzMEGKB=ig1xQpdNce!0uR!QdNBmf?4onu6XtN2ywDf{Od2^=h>iF9?(x7VCqoBiRb_0@c0$u1ZOc@^Vu)4 zGwuA*pVGlRNzM5CaKuY?8-I+XY+~`l%)0Cn8kpC>B?I6$5hQ*Whg!Z6`&LO_+%Fz! z-vI7!H6pqL94~th>el)PF||bPT_P3gSZeAFLX>65mPZ=x(%>!V=P_%1HbV7_R*0Nj z;u;Cn%&+tWU?`j}M6g-Cb|?xdhW)D9B(`sm$YV0Zjj<(ld{D2>Sv`bxvQOTc;C)3w z>TjkKOzm9JOtTv~`48P>R>nv;?4^W+-3=x-Y`Q0q99E9b=5%6_Na~)eJ zb&cU1|4t2I_$~u+bhG523d57T<^DDkvlewE;hV^P`St;QKj`P+iz$I|x;VayAneY+f&96$npzN=8LD9?%S;vg(C#N)zN(u?r zw4aObZYjqvDbuk15BU!@w~XNxV!8BFuA;S3Cf1D&u#+GZ!Q{zZUyp;mP# zjy5WTSvcU1l4B!TxgJF%j>a;lB)o&N=$ZwPUha~9>+=2zLdtf9Ssmmma36^bYbsSb zG1sPak|6!HX<@I*bP^0cWz#$zrF^IrR5EqsR0INa^o5q(;DVIj7sdRf@ zwub=KO19s%y&1iLr|N+~b-We?o&1FR7ZpvWdbF)$3K%JK+NZ>Ar6edU{sQ3ozrR-HbRJpD7dlJ@ z;RA@~^%co(hS#*XFL%w|?N?{ajT}bl$<@U2n3TFdpDo+lhuS~Z zkoNM*V>)$T1|@?B8KNS|tuXzf!u;Vwi174EsJ8RKYIP*xa$kme@s-XID}y6k^TXFs zrVsoix zhgxyU5k|iY&C`} zn%7%n-VZG3dm|I)8xT%Ahm1-M06+LLgc$6Wn|O31q^c-N+C7Q}DsvGj zsW$|;=@Er)bzY*?&KB}M)_6cQ1O!oFouG;U8h2wNwbh{WWnUC1(lX{a3@X9eLBAP4 zrwCc|KRFLw&6E`xFFO_Vd?v}AX0_Mh7g*Uzup%`-fLdY(VJHe=?*P=0c`~ z9rpzx;Am=U=WYMMA~4lgDNpT%{kz3>R7il zSc0ABiRMfJZr>Y0gAw5lsPiXtp+2_VCc{ntcI8gY0>fg?Z@c)ZJ$xzdmGXlo<_OtI z@x4y;2m;>O1;gjw-wgYYRuY!+lqCbNmVpM}or67k5*7ESeEzaSQC<9v+CPW_tnTqoCUM@Q_?|Mr>@i92*GCiiZMPnEfk2%zHY;|xLd zbBD3vQ8S2^xhg6Co=1B?@cNt#WEM7?(`0L*j_@KJj_l=NYPsz6u~GAj?D@$warXt0 z4gs?#MbBHr+m+USwZ`P99*@rni;uh~vL_ z2@6!CDC>ti5y!Cn|L6CR1J+vcs*~JBz$}vLMs%SlMMj)@p=CoiFFZC9jQ6gHiKYQ( z0+ngiD6()r^vf>jN+PZWBE10*Qy2)-8IAKXI=6J91lR&GwH(JJK>~eb_VeU6Yfy7p z8OnMq2&hEyf8Q|EnrA=8JpM1s0;qQV2YACRiYR$yZ(RTD{_a8&d7Pg({4|hfl<9o3 z)M?SAcMiSD1fc<8>YHm!yTLRk!YR@uRA`M@_RwN=#3^XtmS^Ke~D`6<{X}ZiO zS5BnRSfKQ94@)DoQ+iARd%2C>j)L_G;QXC#xXG#ool54O=#baBU5(BHU;i~<-g8%$zCHrsgbf|+^*!sIt?ZRD2?cB?FxO4&kKN`ZP0UUEKcP?A%kiPZ5IAOc2|;-X=~9 zhX_0iJ1b%u9-i~q^a$GmD+X2Cd%czmBF~ouV)T3W3z=IIJjfTmWv75dlm19Ika&=; z&PZW5hBhR|L9LJ%tzsXC?zJuk0VDzr%)X`eqL7lG#>|Xr5uly(kvAvONsrTmjkUjN z=MiH~gGcp5kL{2D=MysV&_B2QwC}>890YW^iGg`M`ov6~rB&IBcwR|W)5MAH3!>?0 z8!`5u8Xe~i^JDddFlOcd5n|t?xp(FA+jxnU!Y3vVPo}U>hEZ##>*Snl9wU~$cvIOD zR07!Tu)`Jq)?U(SVwf~3d7XEkP5Z;^A4kQuLq?eUQ}?&jhsZ7w9f@Jn(gUx{#-`dF z;ssN}9DG*i*$GM_+4Pn=gp(pvgD1}V{Uuv-#i>|$NW>Cr&*95qMWf18+L`rOp`tEZ z-wXC2@~oEYGsm$v8ZC&iIv+t(?xj!gulJB}JJV5TbY9ecd!umf6)M-^8&%9q?O=fSs^t(VervPTG+r1nSTL+byiXg7E>DwGe^FfaGK z2&>JjempC*bV&$`#zKjO2;B*DhXZhCu{W5@S8lGu{&*coSf9TNUpId@>?{QF9k|Op z-d55bA(r)P-Ha|s*==6~-XdHr+1U3Qi&on(L%0@;(o!OLxQG@mNg!1s?~Pi#+wbs# z`Wz(lGqaDc^qk5&YPBS*O!lRTjwIdqRZ(?-={ig!t$L03m`|&?^*ZDV@(7xE3+H8sT&U%0-1MGKf}q3 zg~s&@Q=CqZ(#>=teeXwPakmS*+cnC;m@v)y;p1_ffGMh0y0)Fs_Eh{lV*(rX7W1$Vi5x&~R(UY}G*?sqx zTEFNw>tPO#QXNSIfyu%)@+zUnqhio|tssa{@)lc@VUg$NqZDmIf7`)g~DU< z!L|q_9j=jVDF5d5hXKKtNiOf_Rk6KdxvJ8;#p-*PM@R6TO;j$423jSrv)9DgN#;S_ zlX8XA`Sa&RQRmULuJ{>Jwu4y3)CHDkH2QboeHdEyTXZ=hAfuv{&nouCDV&_PvT)-u zkg6`S;lp<_Yd0#90SVY>?>2f0?)dclz%vL#?!!WEfN=Sd+K*x;$~yFtkpxlc-RO2M zK#zA$Uz2VrvY(*oEb?LjAR8@79<)>_AZSz(X#r|^ES?lZVLQ3j3t1wJ46|;RwQ|YR zdD?>{{Wo!huH`~vV<7Y^(4oMZ zxBy6I`0C1>^=O6)>XL(vIcddMS>>!5W$XZY zkeI(7lLh!~n<4IG^BWmevg#7cmNrsl1xe+zLUh8Z((&F}=ty)Txgec=!Y276DXY`R zaK{>cm6zD!9k|Z-?t~re-hifY_G254y7h2ZPD!A6K-%#l1g(?cXHSZsRu#^Z?)f1@ zS)x3s7{ue?r6(QmTUy6XyONhQ(+mPNVTYxz2QPA+E4L(<0a}UqnRNnW(3?oa=MgEO z96rl=2^f4IVl3974<%(z#}q8Xk4Wv^+HsHHr%t3>%YB?r;5xj2lkC)`{JOJY^%6rxO|QUSm}a? zdN!0cDYUuRw24Mq}qMja? z*{baV-RKIYPO`K@rke8H-A*ob@f_PE#i~KmTTsSVX{ zo!F?cNL(H&_!FkI<2WQOUn~4UFE*9B1c|xDmf7@a>0gh624bcK3>9Y%O|X_Otv94tSBhLjS*>W%m;(|gzDhZ7Xrp_u>9beY`MbmI8(im`o zNYHN9D2=HYPKfY~wxBu6*tlB`pc!T?gCXXn0$5mCqY!-UvVS{>rd;(vY- zu4EYKafo~0-BKuP$;yT-TNeJie55&SCzP_Q?2OM4*4_z@bytnAIB+HgYeb57werI1C8@zZW|J)MZ zIW6>%97M=;Z_u{((AHNL#2J-A>OjZQi|Y3tmemNR1p0I=K8E+<7=k^cWtvDB!O^`> z?Ua@!KV1ZIj9JZ_11KPoB;r zR7>`)K4Pf;OgN>7dx>UUQE#L{!6>MY&pv)Cr6`NK#TF%%7}I2Grh|i~v`Y6Mfifij z8X6=L+9qDV-VXeGS(KesTjKpZljWx@t@K@o$W?|%74ff){0d-8HpQLPb|T>c~pY3aSIsYN<&GLBP@GxRFeY{Tz+cp z1oJ!3?8#DpYt!66A#mb>1xXtIFJb6fE zC!}Cym`@OZ`|X*JjB_qG?xtk)tae>d?}jvn4T7@ZC2w~eYhG!Fm=|^Q4ooYERozQ9 za+@d9BlXW(q$53Hn_<;Y{(+5lt{fL@Xxe)|&NACzvq^1rhNY`mhYL$)`Z#fWr5Dka^8V2XL@s@&1sxmI3Z61lN8o=wA-USO*H9Tkzro=JAL-o zIYO0Q&pbQa*6B}P9Iz5QI>&Im-!=VzcnmoJj0lH>rT?3um%HYZ2}jou+OPs3QuZ^e zlM1h@ub82#)UbBA=U2C9|o5}wdnTOBiRhH>5? zuOQUGJfiDB*gNfr{^#UcO)Oiv=e7truyM4(UKRzuM*~R}+jHIiO|1#0C|c(lA{Z?y z_UFGd+V0S&mVTU~^w{VdL(B-ZrTP~UA@GG|HVN1#bvfKB(={Dd{3=~%;gN%|CM9t` zp87xwm=?q%)85_=uWe_x`YQpb95D>T;|-3-{CQ`>H&kN;nmI^C;N$lXUWrZ_}&dm1xDsjXCQc+=P z)#BPeOf)yvHB{)miRW)p&vFvyy$t1-Px4zE2eL^OYdm57D^!it-nO;_XNy+|U{jrv)v7!2jm(Qki8MU2SPER!Q7`%Py8g?5ta=sNVatK({*1!9&tq)466R=N`CTgof zLe4G$*=WO&loHNR{%b(+mZKl((v!DF!v1%~sz@L_qLd6jg6fIGN$(`(dw51=A4L!5l&8*>hZ-O;P2bO7v&SnIO9{i#@4dcj6#YznHjJ` z|KGml7ZYO8zxe=1$?xmaso5*rPt&Zz_P>RZ7P5))#C*uvln*Fw;6TIRw?Y5^-yROA z$uB9ys4XFt!|z<(Cfwd(_RhBo7+Atr^!9DcR5y&*a_eDOns6%# zA4pI0WQc<4?S5#H>Ki_=%Q_PUoaUo^Mt*`@Y|CB~?g z=OgO?{GBvhxBN?#{?U!T@rz4!_)KKdU&XeHksyL$sU2~-seWBXo5Qw&Sa<}ZWQ+6V z?HEDfmR!<`ul@yoqeLH!?;R`&6`)D*+kbbI!=*{hB&H$Qq-8e+HCi9Bmm9y`{w#3z zSbT3@7t<+H)wS)q!L*q+qKLanF5+^LTon;m>{1<7(-g&$0PrfRhz&Im%~jKbTeHnu zErX7sR!1~=riH;`2mcr9gDZ6$UzWZM% zdPlSDOwxn5>Dkesj|M4KgeIzu=)xBt;+xT0DOM^bQG%+P)oq(Ja27^Q^J;rg-7i8} zLZEDtAzN~D+>PF;ddKj*dcJpaoSL)pd{FV08c#)x*%3voyP>QCP{>DZs{uMZQ6;!W zYT;^kxPUyZdg=+(BqIte(b4dhhu>E>RWx4DAf~d(hUCm29>0}B;yqa{i(7nfpGDYi zIGY!4yiWDCn4wv3pSSD~u{(XW`uwNLnu^I-eU|T2sbzuuy{H>W2lCc3aa5q6`bG!F z`VEx44dRhrGO_Y=t5C=Z=Zo~mzRnNdJ`)EtZqXoIJ|K%Q$glLFtyX15g|wEA?umTU zV+JzH#Px5L#$+4T1tkC%Pli>s*e_aFsfgopMun~H@6~6WG=(%OvE;y*v7AZItT*)e6^9TSxq@2Dr&6yzSb*@{bes}pNfGqyElm9!Q0 z&ERM`w()l-MT7puLQ5kfs_E3Gy4S&6g7w;Q#8u}YCMeT1poyOG0U;?W^RwznRH{(J zVxCv&^9BDwANSb$C4i_k0?D-*+;~N6k-#KRq2~hl#$NpFG(Dos8?c89NuJK_ao)!o z3Od?1ja4<9WKvT9Sm@z@H4}vF&@nN+H=aTjA^o03OTF4j7ujWFEQS3!Ke)G`gBF1? zea-rgT;JL;Kt_sZKPel|&y?atPrMfveBf?gy9Q=w0PpjxVrFbxkNiFOy08vNnA?t! z`h|o@0-b~cVHC|osM6F3({;7vaOI9j%Adog5@2hrwGn+{27Ym7N^)-I@~$yV_ukeJ zcR)Y3BlZ?+k~xp1`v|&!5#cS~%UhqvMAJ=<&n(j^pKli&`Z$TxeL0wf{6I<$&+@|# z!P1eE;|uTdghic!_B}J}Ee4419>jl;J%Jd+tqG>L)$FLF>7F+DNCHSw-C}%nto8K7 z>bn~y&25_A^A}7&jU5pLu+kj?_{L(2XWkAtP@Cc-bB_2!)>4veBr zn8IF6#ga=B%>ameUuE;!b}Xg+9ePqf2Kb0$*E z1(AnhNvM#j6bgw3dp8K+5uqqOd9pK%XcBqIQVBRBw&l<%xU~H!hXV)B!f_AVKmaKI z#rsh@TcPjLTTZkvfEOo}Z(w~#BqGZwU&)o$}Jfj$T7tr znvv(~7nrL+6PA}2+2Cwemg5N^lBeDtYb2x2%i2GSprwj)|B~btJOVlEMq#6GTrj)H z2oDxrH0SgVW>dK%zm9&ch^WHRvgmG&?#jxRnL-TR4uvHWv9v6DAp8xy)rw1DLn{zu zL@5vek=*F94cmMW7hsg3*x;D8!CnjSvX<;*ue*S0W`07{5{CoV7j#)Vri!x9JJwapACZhwdj;sh8riv5P-UdnG(aO3@6{+ zfGu`2KZ+ktrGhQLoK!^PZBn-)mV_}qmMz}v#cf!7&N^S}_d@Q%(0I5k$((%xAs)a1 zbL4UzAqtemr6!?6Fi>PL3WzM=3_N=+Meg7y`dK?@PZ9!fAITRq4!>CgPp44QzV9#| z6WRO_-8x!FNXiOOV^{TX`ECh_+K*$4gu&q8Iy&*FYM&gm${_^sM<5SuLVyLd9xSq$ zi4(Q(3(T4NWWH7?@ci zLxd6)1$A6O*zZ9&7Mcl?5l_j@!T@QVYsEZ+pK$8<70;x1Y9y-!3G=O3-Eo0PvHT zk40xiW>x|du-J>%b<25pJNm7$?F$FR6_-lUx*MKP9h5kq!!o#iO47U zcqkV3Wi-h`jkWuV#J8fam2?&`CFzWWu|1|R%DFHd4+@Nq=a4HT>dlVL$a+KMN?mMX z1R%d?=eEH9PgAz3Kp-zJ3#VFNfDBk3O=|l|nCur6GRyN|_y~0J9%C7e=I)=i(U=!` zckkhZ3YS>)P{Q|>6y2KOg>O5VBJ_?9zJ(?#ds$ozn&gifqi$yQR?r8tOf#!RQ}5%6 zh$gi8*?0`V0jsN%h55T$cK(P)!LMNhTz{+ki+G%arekAeKNHGA`Rj*Z&;O@H*O2zv zX?wrj$hSFtgvP7UE3_M6)$ZY)Pc|73c z^WF8{QFTkMFPi>y`><_nK}!Du=1(FdLrnklO36#FSzXOKlv#d<=2K6dmI-|>|M)0o z4IV4TC;&0owyN3@9`|V&dtd`7&?Dz_UX5)gM+d(;Kal49 zj4a-b5XyJbL=_5s8I)q65|+NOF<=t=GAh}SJB_z926j?aTJ)>^xd=Ta4<7yH=yT)SlsiuVaH+Z+GzCB|T}!5Gv>H2kqU_XZFXl#Tv@bK{Ym@x9D` znXC7&uzo!>O6d1Vl4FD|qB|I8sZhwcp5gf{Ag#B%PuVR-K!^;#2l89;mI(;V7ZTct zgTZCs8YgU^ut&5vl3G{VqmbZGlm4rIGjMXK*ZQzH7O_@vb_jR?CNa0vyp|;zFcB^j z0U%s|@7S2EcP`66xVtxH4=ANA(U z;@g=);9HlE9zNGFgKEL8t5gN+`o|XZZrMDD&~#17=8AR+7ZbEL#IC|oHZKnh?i8N5 zzQgV~i81XML@Ch;=%)5qp)iIluQBDfCDs#HPc^+eaWwo54U4it~`}b647-D=92*DCRWq z>h;{9D9s4@WFLew*t`REUU4@>617(Ur0qXcpZX00+$~*(!`HODb$2&6h!i~8oEv-# zh#~~aE37u+>Uqg0$vj7;n*~t6X}%Q1^=IW;a9=g!A+W>XMp1%@H)xG`kT_$$y;FN5 z2OPx}FhZ;`C`nt0gf8y&32e+WTds}ku=Gs20k_D@#YL={KOOnF&TJiDdXn4hZ$B#F z_Df8z;Elm2*W~YP=^2Hs!96gfZv}1OuO$awP)k%IE@9Avc1E7P&0X9WHvjmVx@&gfU>g!gQj8Z9x%vUMtF1NVAdYa7|hx^?W_Q!oDsvy0~nz1Z5!w zm4rmdJFeX=?+h>snQc$8%GqUV%O-=f@f^1b2$B512i7STKs>%rr>OD5wzHDEywz0f4Mg)@&ZZWL(<_y5ntO%~o=!*Hh`@@{`_vq7RNKPV6^ytChd2BN zS4hjTk5DP1JIIxRnpdqZ*vQDSQYh_Q{qS@W%-T`fkQHF|DU|u<423SeqWnY1j@<21 zJ{td+@bd$=koGfeT7w&Rd%D47aj=8;t0BugRuDukY4hKdQI^$&`vKWx@ZuKYhNU&> zAGus|$mGt;`Qx^2|t13z)pi%7qdltV%na&1r%n+Y+!)*+R;1Kq z{b9IL<3CHXI_#>+OXE;DFIJ+@$K1=cR?%fv*OIc|=aC+by)F1N0m26x-04}hGS)*P zK)|Zg8jJ67FK{I_i1>a>z9C4;ij!z+>4zTJd&9SHKmY`dAsAO7bk6{Z|7Oy3w}z0G z9V~AtkvDKLia=i+FuSYfU$<|cvT!MwsyPZOPZsA=zZsG~#yr90#c{4}Q7__h&JOSO9jWNT&NO)B6dx>>2$Awzc2^G5>4L zw7s~QP^x|DxVWT~|pRNoLvuFmzqFZ8C zHYsc@qK0TOg7Ltl@I8Qg5r9Xbr3RH#B+*iE01);-AqteGq6m<1k(A)98D)&oWgFFs z%clwiQGz9=*%D?9oJZ_Fudr4%8R1t7r8nJx>-LRR+rnFEmklOp!E_x)@Xr>rxEugQ-ZoFmTP_Qoxxpr? z_z^YaZrB2N-Dk^+ZlM$55KVomtwsDVUl`|JYtgtWE|n^@iRh`KV-vbg>@%;A9DM+l zlnT{qrlz+>^9k?LfSaLSoRwLy}BHQ#r!95@0j{bE|uKEHy(gDWO6A36gW6xdW765IzWGiPYgrF!Fs177X+o~F5|F|p~ z6-7#0y2+pO@Wq(Ul#04@%qUBipZ;tdq4WgKELss+mWy`Ux0GnODC|mMpuFcjZCtV{ z??dodBN|J$tX8nTP8p|t3Kt5wAqtP1AV2^AF=(T)5eh;goP~!pl|ii_eElIZ>1q<3 zsZN;**DcsuPZMC*nu!!G6ctCYY~{gkanh3_Q)5xrSZQ>_Omc&u7DFg_ylS2n^3 zv_;cSW|1)gw$$P51X&|8c7=vY6se$j@9SQWdLFCWxo_?cWnn{D)R>W-5C~dOPf{4f2Whe@13M0hxmyB} zu8Q-HfYT#)b!^naBHr)O>rM49Vo;S&ds*Dmf_po2f~YpcZsi;qm> zMRW9C8<+9BScs#&phPk!TQorqknTR}$+}soTPu4%OD5IO zzWlKjbo@UnFizzVkgNqFzeE61spYFI2DyRHd9w*y-jV|dIM&yvpumbja=Qr~4 zu9~UYR~Si)aJN|uMd4UV#oLi(C}G(Z(k-S60N+Ly1-8vU9!EPceJx7<9CT}Aw8t+kLk5E?+5#qyzk5qbHrCcmy| zeRn`^=&I_5OYM1*)i#XmY0a6SMnVIZV}S}e7b9U8 zQGD)efZje$WoP^{xgj_+cJ2u%XJcEUcKBWz54@E1!a{p{gdn++n}cb++BD7xO(zu+ zz~{&>HC|2cL^x3qrI#X;d$@H*2sWk3$P9KO;e4ZYRBeY(5t#pFPEZ?cXvuzIb74(S zWI{+ua^uhgZ%ZD)nPh5{vJX8S}b;sR7tsnO_yI zXAOPxyalp6&lOgpgDB7uQwEVC3a>e|kjX8*Rv2duV%FBJ)v}Zqu3mPSja%8uK@CX_ zHyTAYRfo zj@6Bb+J(#;C{<@0HSJuq74RM~)Ng~)m6^|C60y4L;>z@pH$;4B?41D6{Th{Tv@uC! zr-0cnVU!AO5=!E^8b1HBKZ%Gb{n2a>6G$GOOQh$(Gk> z)4f#T8V}`@ce9vZ5>#f7*_8u1S>kd^76^qm;34T%{aVMU3YZQ}Ta+f*)_r^;Q*dVe zeb%MU!&Ac)iSHrYIH;YpSlrcNJlF#>ub`m@ynxqOm?nHCS;_J%@@hjb* ziyDZ;-tH*PV*EyZZyoIeXVmd5{zQ9c$$OFk=XWePa3(A47#U5p2->vTL)fZX%=(B5 zP;OY_T2oLtK{u*tD<5)divMS&=MRqeV-EMRug{XYPi zJSD@ix%}@<$zgkHVEx6;YmsuAluT`e`r}hk?;9-PgnR=PGjq%36(Qef)_3z@N2R*M zR{2K$aYJYfuBRQg+|b^n`tX_~Bq!oTUkJ>F8KXAxW={CjyI5)rYw^>*UZTRye}v$v z2DP?-<%gXG3|_ZTql~7v8yQ1yT_Uymo)ix)rDYjsJ7Q!>GT&%I*v!Aoa}k(y+H@@I zTk-8K{ji7;<(YfKx|gU7@9jW`BzbUiCE0Nhrnl7e_v>$O@AD3u&sb=)cR1@7e#BNU zTONthV8?xV&;iq&6ujklB?p(%#*7-LWk5n3wbchyv17#4zsOL%fJP*GNE?#>UA;$VYi%z6PHi<&Ue}mD;Pzx+d5itzVp`VYe6kP ze>D*85U7doraq4X)xP^9;W4&Y=F41av^0-D=p+d_Zpi}NlsUDibJZsKDh+s3?; zBrw!09iRT4D`q*l9+7xJf2YH@N%F{Gd2xR<|HEeiO2CzART=dz9Xke7^@=PaTm#285L8ye?U&JJf&VK#*W{-(*P{9XEnL*V05SX-At7=R)SNO2mx-n&a5PA;E$#5=vlAz+rL~1&x)edtOP^5@=|;1wYuyCrGc61+{+VSB`DI4K1oO^BA%Ia*))9hGU=w4T*kI-Vmt3t^4x=GQz<;%73A9Sd zx%OGJhc6P$wW$+uwyg<`r~7C3m~GIGq1B94xBWXzpUj-5jPimb*c$MLsu2H#sNq)^ z+r!RV2&qm=opp8@IniryD0m^Buo|QrIl_vb)Z--g95(%v=>i`Y&62xd=Jf5VB{U~6 zGt^nrkX(>?K!gm6V4C;GewX_uNy~d<#TIi%0|wAD2qLV3n3h4HN&sww1J1MvpUTKGRWoA50St^XFk66ZP_3Pmm?iszW5`7-AZNj5P*Lc zN*H)$gjFkOExILMpwkvw0^B9jERoPk?uV{mxjG>O&hfLvb|?@Q_dwQ?i`@4*qoslr z*uqJ`hm#gVQ#tyd_p|dc48?HB37@O00#tC=k*>L31_3nJAr`xaZ2sf>*=Tr(0A(sD zP^kO+51ZM#?M&=V=BW*iZ|b}%BRcgD3Ws2>N(LssqT(u9ET?qtP9oF$LYHyajp^bj ztS45v#^WzYdnEf_sWslgutWx9mbcsvU833OeIctpNqaKaIEv59)(`(B-VN)Ito5WXN4nw0+OJON?H8{ zD1u22(W{Lwl*j<{0E0$HltE0kPf=Z?a#3G4$5STs?55lrG*e?&#=oh7-{g_gYa8Q# zOGHz&&{0iDD=MS&awI{u#urwlzfLVHZQL(Z;%a0Qps3DrT1=w?N5eA^9;WWI{jwAk zt25+r;K#o=pp-O__ zaLwbI-;VeVsXc=hnbD2wZ9)Sgq|4GlL5*|o);5MrVc?mgN_5fG5Z~0)$_~=uUH-*S~Ys-iD)jY#(;;|k$_5~z-R}Pbk+IgwoBr|M&d}_ ze_fIIXzjDMbP#ZZo3INXk04yzGp93+Rt8K2#^n8UA(rM$!h@@&qBVfE)>3TeN6^z1 zxLR~5({su-hZ?eB5KB~3BBxwQ_mq=LR^|S=L^_Orwpk<6pBUKJ9nU1_e&#j=ARHtN z25Wq_qU~F}FpK}d2SsVwJFG90Jj-{tgeoiR;1A`fqL}PMH9u|H zc~n;#a~gA#vfSgzl>LlMsao5Bv}=_h!iMr&MKu7oXC+U2AhGf zCDOy2)CtUplC`=oefMM9DFSEZ_5sb7Ny2+;FnD@AprlqRteE%77$wsU?OCbt_i0__P`z5P9o5V-O1k=Hk(dX19;36Wv>+n!gW!Duow# zm8&a{R5j=067m#9z5DS~c7*fNv(a63z`Vt-(bleuuosFaz;JT&iT!P^Po*2_{K-)>(nd^Zs&@3To_3*=WddIuM4Z zA(3+#by(04qVmCR`hbXC<&C@dIXVpI>ah`r2tQx-@rkD%S+SD2Sg#NL&UBYh1Km)F z^xSE-s!r0ER2EWDI=4YSb|1+B{GGFGvb?Zd`Je6nNpl>SpRe-?!(Irb)&;An)QdiN z6t5J{W*0ftLNfOR0YM=P zaa>l)Fk!D?<^TW=0|BZZ%6|X=s^p+&WqWIB9MjY~+~C7{<4~VO7+!%lC0%J#%ec>p zea{|->bHcj6z844LcF?#%s|@I`?{Iifq~khA+()LWU}k+EIV=66&V{L-+=u~$ z09z_C&ofWoPKq3xX;U3ggM+n%mA?4r<@P8mK&Sip^V-AU=?vArFzoz%5w|4^qMY=q zUqUw$)_%QMDW&eaYT+bF8&Li6)%!Un>=!pe8d5^X0EYi|)f3IhFgWjUEn;vN_R3$ zB_R7tQA6Z;5hOrt`JI$F_adOK2} zb|}W!P+Bs*sF!O+Mf{t!SEE%3sHX*#{LGJXOd3CYlRqa@_~Ky!%Ew3oD9n)uo5eAh(oX5Wjuy0&2Rdvk<9~7e)6kjH z)T8{MCIFck?g3ZBysvQbvT4;;u{Nh0fhAY?cY%UJOD@cI3@NLi4aiPXol1!8DEb#n ze@4{*pVa$L5;ISZX(0+H-+PWvdnx%C&Xiq@_Xv&Zi-eBsM?-|zy_nOF@1g!Qno~Wx zwIAY!@2UsVgZ0+iM83ya3P`4mKWuA_m~x)DjugImqGb{aP6zD~+M-Q$6QS&sj`xu^ ze+k88CS+UoQ#H?El(v?%CLm5AcPCW22TaCmNDqkPM7)U9jU7Zp#87yK!{U|bMUF-u z))l|NS*Mm1q)LDG&^b3H!Cwtus^14J0 z{(kXeyE; z$+2%RBFiIzopk8|vxC$g2%bp10g+G$5Mw*KJQ-ugyZ*@_^a&e672S->9z~ucpQiDV zS17h98mf+Ytb(w3_BX_3r`- ze(4{f7)D3qFF>UurHw!?5Nb!>)cJGRJN${sKKa#pjy7jXdHeG4 zErYs}D$R9m0;_jURzWKUl(k+tEdtG*5*e3VR)SU_VD_Q!>2H2C{j5ng&TrT->m6P$ zZ`~``oKM3?S=hl%t94VCWD&68x)gp*+wZr{UzVD%OT=k|7@(AwMv~uG${O=E%}ty& zGyo;2C7pC<)qJJE{eTP8b~b6~SMa-vwK|*GX#@J9;$keLPw`?1@eoT}d}1LcEJZN< zoE#aPwOF2X`U{=ax8;Qb;WR$wfri1!Ykm{N&S4TTNJg^+=hA(%cmC)GXY?TnkE^wfVs9a2GJ{C@RifZME;=~x_!Dog*!lHpRlO>brY02%4|W&_s?E;-7F zY4lm2&y9;d2hI^Hu}!{<4YlEVG#t6%>ZOBp|BElE>K}NeR(fQP z(#fI76ZEmObyad;Y5VuZY{PYv5n-fSv!)pV8Bd%-Z-efGX&iY;TAjCXvrzK{W;8L{ zGH2hI`wE?KaPVt`S#3h9$B@Tjm{F!P1q9=2^MWF+cbQ07Y}SEB!fW%pSs_;vAV_Wt zE>)eUkMfHzmmRX=-ikF+ovsT@jwF{n+?cms{IK+8BF+j92F8?`N8^gL^{BAU&opXC*S{l1wyo2hIJh^OgC9NSlsMBbWMPU zU;1^}dov%H8K+_ws>#hwk<&Ce$BQjSD67*7i%3fWUJ|Oj1GGoi;W_ea>0pQT2xva% zWpJNp2%-XEpMc@OsEO~$3bsuNf>zF&msr4&ZH>o9mAF8+-(^2QJ`Y&Q2gh@V_aq4~((2CsH(TOjLDf zuAc#08yk0qX(4u|Nj)v_n5rnG$vW|m`eDuaP!EZFn6&^8(*0Le`C>`E+1`=GNy?twqDNg z221Nq^#gv;1pYwld71z8qn~`TrMzSGOMB)W5O9Zs^KE~5f1}=Nnl|V%YrIZ(Zqa?x zja{^m2IV>2A{$kEa`^owxPBqr#oxO~`R^u%UPJer|0RWCVOsONSe*-@5Ah)zy)@|e zBiVCWaS79Jv{IvF`lfR_uT5qeiYj`}s^aqI+ai{pqQQ3u`k1%9nv$CU05PK48U7P| zoCT1auZg(G4Mii4o9&Y2dihl+ZczO_3bliu)L7J8Mprbi{z9VJ83>CWkAbA&0*aSj z!Xt$@wPK6bdc%AFC+#@)tV8n|{B3Xbp(>4+Yx(x7gk^-!acuRy*I;?#x(tOI){(;@ z__KFDc4YUTrrhL=eK3UJob8f4GwG3zLZQ_;ft*+@bf*$>QzlPx0*oX1hG($2nT{%= ztg=cSbZxm=rNr%N1boXBvXxC~dwEi?V$V-RHLBOQ{H!=LZDvb#o~k^jodqwX zg?1#VQ1i1u-IDV1vr_2ov9S<>kAU)YS$WyY3u$=yZ5h5^BZ9h@0q}XLZqT}?uL@z; zEz!c(Uacbg|G_xodgcSd4V+=A|JZTV=;c`}FKRYUs;#5tk<%lTeRCU6tEYUmfv>W00rHG!jCRGv|;u?RsA~B|UJBTHUmvIVr6F7-etL^_|XD0G3 zs_QvD(w^TYpR_~1XQc5-r{?_s=8RaBx(@?N*=axEaZIi1bR1_sXEb%JHy=;Z9#KQ= z2bW0i;X-s+aJM9#EH)SU1W8FFR@tbdd%z}7-|2Ia&ypB6OmE!=XCzed$|H$$xuc$zyt--jHq3CeHFE3%1Xvy`*Hm7TWN@EtmQK;)C|GtV;Z$^@Q<$ZK;Itf)KxYQi5 zp^xfW7&zn@1+8+A{K-`w&_#nJq8kSiZN1h!@c&?Ic)jz)= z3}d^$SPQl?sz!BM(q5G_IL)4OZtu-yeqPl&IHCL>2Koq;f$!JB4uXM2PHSkDwY@OMj(9(^|O+( z^Y)t6t!MR;0L|6q?=@@SgWNp~XT91kB+@aF&Du~>cgYN1< zj8WV4{Ojm>M@_tjjPIO(^rkb6~B8$GTh(}WSTcgUuM@O2oqUrAr)?nlbBg@|2hzyX%?ZqIUA~R- zvHR$yzeJV2@D$z2EYW3|k01n&w%c4Lql$a`(mQ+C{%-*$Gnl3Jb2q=C%zlB;yvR&V zJR)ofn++)hOj4pmV|-kyD*&(*S#-Yc)Fi;~{JVJU?uiq540Fgev--`@4S*%vw~moM ze^#f3$c~X_G9`e?Q~n3Lb0Q3d2aXghEmPC!7b@QP!loQxP>GciF--0Y=j@pTSb!=m z-%m)$bC7ogcvV?GInFI`huf2R9RN#HJ}PiiSu>RmmKiL>J1l2P&P`CoAT6(Jz56{a zvAfq8#-u2>QfBz)y!Ue!2LJ#&(IM!{B3}Ri0{{hq1l?*uQYeSG2AhLy)=YPW7|2#- zwRI=xZ}$d*DbK7i4keE1*lJU4(QtXOdI((*q4RrA?MXCkVGu3mSoT_hYokO1=Z;p? z9$-DOhOg#|xEmq0;f#TOfOPX{WnT7Wk~3Zcku`jrOygW=wn3|i@R~_KYV!`K;0XL0 zni({I;#kQZ>!G%Sg3T&WPEyh6%=}szpAGhl>uQC*3AKpCylB2{diAgMw`d!dg2X&7 zc5H_bunzs2y=LkJ$plppryenEK+34xa@ULj`G4;ezlgTB!nFBf7N1E?LNpNg@MEVe zDvk4Bn|$RE$(h7cRWD3h)sDcYKc(L@-u43hsOXo^@1ZNXv$>N_pZCS8oJv@WD}G7} z-s3~i1i9qx5qJfbs_rqrdq?!bqOYK~-RHGaV1lUBFo!9wxhZc!Qpk%;!FR1Q@JybG zvJG}=zA~j$#pd%o;UDS;xS$pR{!vdkx6`T&nqbxytQP%B8a1X8p=kt_#XdjxAG*yB zM9=f$iG!JChHZJ24l8LjFp?}n@27H(j2RaE(9JybB&@yK_2oEicGs@$Ar6vvNsoLV zfhKiVexHuy2Y%jpnUKdxD-JK&q3Bv;a6wkB7y#3VaHam>jLeB$$${?q!DL?yE?)bx z!JE)k*r0SLM$$X%WG}M8XB2280L-byE3wx|?p1T#Dsi@SuOKHJKN$wNet8|RCOW`^ z@!#u@LnfWqL~ZFL#sQemz$tD3Rs?^ITb-l+*&w0j$)*hmxOuKN_BEM?QE{MX)c#hj z_m>^^Biu1WHJ*xipjonzpjq8%bzC?Yi}=BLPc%Uf(&ME|@y;CV-+BUl%lH90UM$$Q zH`v|VJ=gjj>LaAj8<0=<|JTXbr@&FB6S2z6Lu@0y5VE>Mh-=*z=YEyogx%WNt`{ zzJnG**kdzS^X6Rbk)GV&wffP;4JHYwSD^utH_?Vx*8s(9u_6sUrVOT^SG7PdQzlWS zHiaW}q90<3B&X z8(AgvU=HFn6@H<@vCQD?VqSG1wm52*b)A_K1H-8KXz$^MP=m{Pn<&-i5ux(WRpQ6Q zb`th;3Z7>d>RN zoPS}DC*DXmQ*{4>&zn%FEPMa>t$A+4>Oo-nwLt`{-6pq)G5OLx11Un`MaqgkGjXey za7dilIWIGD%*I!oHK6oRj}Bkw)Wx?zB7PK3uTO}KA-KQDo&K>Bk2fmlW>0g+%*H`k zPQVnNTvXB?C4TfALe6FOFbLG%`-e^XMJ4B;U_s2??Y#Eo)<7UswDst>&lkP5GR!Jp zQE~a^e?v7x*PZ>BmgG{bVLFP?K_fHVyKW>A4M=DEMdCX?ZLsswidIKj9zi&2Q`})< zlBEAhZCGdQj~H(pp)!VH^fi8j&m_n5b+jfW>O5~}jKT+9U^41%n2(5V9jE^lFPwh>4ijF;eXRiRRu?b!M;AY!a3hVW-_k_vVy0& zJ{na0WD10qM2uw&kxpcVxR^dG%;RNhk`-`04oK01kajvh6S*FcFxBuoGA zla<3iSAxfQ)Rdsr3H@Xj*}#An8yQ=V{)<9m_oY0=-(L)xX+Jgq+Vbs zj?d~eR!1!g95Zl}Y!gXP7uzktC6^D>15;@Qj8a>UW#+gH2hzmLB+24CFNe<|8W5R> znNc>$f|N=7-Lk8|B$P&uaV>n~dzkj}VT$-F+P4`haSjAKVqo=jbUm6v>r<9G#Gt7D zzaSrjxL%Koc}ib^EMOXhALm8 z%t+Q9nRb|{KHezvGkeKb-011V{HEtYkemr$lmjH&5=KTl9J zq*>G=u!poUuCO25 zke|4DZ(=e7%Z#CA00tA-b{c{HRc`cmMD`Aw1fSvec50h5uqIFCfveW1#2DG_%S5-D z-2kc<=W7YlqkwEn|AY-l>qkK0@WuVu<)MlD8f$5r|qWiTfB!>2)l6G%_)gPns z3+m2Az<@qaY`A=C+Fy3G#ZQ7U0rcs&&hAZx8RkE@(5TR}%`qyU%)+rdif3;wD=oe7 zRjDCa$1g;>LUgES(_%uevGiWcG6j0?zZ3U4w81C`+BW?{OD@}!*0BlB*>%fYZjfl} zXXF>dE_zU$n{IG2o-wgfLj5VM0Vdr8NJhQPv-40H7lvD)HXAj7rOO6;CUwv5)B?`NwEWa|slfoR~QdC{}LJBKGYio2;5f0yz@knwtPx5G>x9Fdx(W88d+m>-vU_ z`{hz#(DVkL1EXw?uDocmmsImOD*t?v*QSP^9E!;W07VQoD-2@qh) zb{_ZJ0kHc}9jJZ9`tHV$1c!r^AinkP3U~;8`f>}C8&1{6K0eynGYAt@LBK>Mx2^-} z=`}1pE3wSS#)7O=nvK=&kNg>xC>)LUjB8fR-@DmeoNogzNUH{XB4H$@FWHW! z?%@k5Zz1BUl=MCQ5j7?m1@uXO&OC@Az}_VJli9QM-!E`U}R-7SRQ+5FdN zY_133Fd{xH&Xv~f!-H{bo07V1D8Pw4L-&62Q~zDR$OFLtbTf4#b_?jXKM#)X%^N=C z`6~z?eY75~KI`VI_|2`+*WO0|K2KZN75g^T_?VOFcEv^R8qxsl4JP5zLdz<_)7;}> zNye9wKwhZ6QZ+!_xV0<94uIC?KWeTBQw?>VYl1$#lsJ=C;vwI=*>lb8DiTf^51?dz zgENs)1xyhqjD;qK^yU)0_e_B`%t)g(74L85d;qMOC4@q@L3=xR?ANYZ`jtEC)80npMty^`o~g5Wp~Z<| zf!%GPreY*`Sg!N-urNHed~uHvR)9>v@tXfu1$bYrRr&|Sm6E;J!%~@0C?^u#k;hQ4 z)RU;*p8$)+Ge241OWSIH5o~mj5R?2y^2Q4VW<;6)z6Zx);ZS;xTbBO%ELpXqbR3Ii zAP}oF8w6#}{ZUL4#mHWmPZ|q02a~54^vbl*YW&&MQME<*iKLIDoCR*}lR3&yzOlpG`GL zBDVY+97UVH`GF|`@$ahDvU#$X(Fh_ko8;-)24BS(s82qr%LB&~&(0@DGN^0V08p@N zNCY8z+Yq!~U<#)ByUf< zRxMm-i+_Page)OH(5XaiwP#Me&9eoVzQNXA|2WGAk$8-*Yd@4NIwz<}IIbD@`yurbOL+|Z4?A+EBec)BwdsFI-3oe}yL{x2 zQCeS#w<=GYKyE=3txotFj(Q8+m~E5wTMjN(A+x7C;YJyc_j*TbTm$F51Q-L8Aaa3= zaG!RzIZA++)a9~Lhy#n6Kn3V>s(~)lV$UA`R0C1}U0R{xlS#EzBM}-zt?z1@^@QR4 z07w02l6Ow<`y+NKMnZfCflxewfl_UlGMc)3ysXzhcHnRQ*93e47i!U+ zt-l}Cj}JuBTHamClu%q5+QKbJj=c`Md5wF=fnyruz{f@L{6SYs#$7Py0$WE?Xkb zg}hn*!H!Lg zz^)9}>H1#y9sZNQ zeWG&^$1|&*3WKOcZAj@1p352V6c6iZ8KD~d^wnzVZnc01sT%A3 zIp`jy%8i=Gy&u6NKCH!dEj3$rlg$BFg&aBZ9aCT+V^QEoYE{3$MZKF0S^xwuNJ=X%%~Dm92<-=5M(OsK1@5~zG>P97gDa_7r}$RN!T0umjrvvH$9KXU1Ju0 z^6vRQ15*%w?G=#rOV;T~r|>>lPVh|Rf&7p}`vFA)1JnFU7)&QJy|BeGp^J>>g1{ZB z-Ub+mAjeHU8nl8I3tDU&&Rc&$xK~2@&U&v__dU{gxUjwvEzZQ|Jzw$A{S3p8am!Wt z*C&inSmQmblaA@?0Y9cff+_xO8G}|&=-ymK5V33eufBGif7_%~RCj^?So*8qHipIauv=sTvHjZGC0;EI&FS=} zoNz{H{ASwF1@-hu70Uc3Ec9;qtAotxEsJSeDx+5R7r_6zVwV8TPJwAFt_zjqkf#*$ z&6JY07BJcGp3{>~i~p7H!%<$M!1aKmuSWE*L?m*nBFvvSfeX)kjZLG=`|8_u(;_K` z53G*^C=ET$Gl1x<++OrWT*(GG0(2^@_5)w{E|~bz;MfR`LSnd4dJ8Dan7uj2D1;uf zX%!>`ua@N?-RJIpBVA|nTxz>qE~pC1s>9fE4JxvxxY;@RhFa*G7y)vR3zUT^rT%+K z>B2qObXW73t#}0FY?T%$~M~6(`6tedXsh5fi32h#8EB8 zEqYRtn#$knHl7Mqc>7cWUlD2@Ke8GG@~(6>&?rTrb=|M;hpg840r&Hm)-`}W9I%c# z9Uhx8#wOi3AwsUi^78Q!gpy_^>F2FMlonAc7zxg)Y_^4)NJ6QsIS7H1g3_nF*clQ$ zYF~AK75Rao=JjBEPdSd}U^Tm4fXuYeMLuVau>iX^SHLTym=dvZ24s@+eP=>(2fWv~ zuqL4)S)q9SCj)ZP1_0(<}jpNRb`(HRL#6Bu-p5e82^R;BXxbYtBJn^RYVx`%S>X6-GhI~EJegGPzpCmEOo zPDW@)-e_Y#7>9>B5YZvc6FFGV`RxGEC-S+A3vdW|*B|`uN6$lb*rWE?t=5!8`tib? z>d5q6?lR@3FZ2@*)p-V4oY*TF2 zC;O!i&a*NMwqDgAusBX*1ZY#(Isy)lmHPF`PB&4kjxtVztyX)TO`Jxd4IrzA-~ z%y$Z!X!Y6Jxe6h0tSkzYOFF4oM~*)a1p5V_pLMw=;rBw8;__+l`{U-W4I&mTV$FxI za_AyLlW0x;UKXG5Tk2FX`Tc`mBE6gRZsfTQIv#|(i}{uPtkwGtp7N=({) z=#Y14Zy%KHEdlOtV@g}I6(#pJfNqB!!(zVyK`c`^xf2u)ULtGV+R9mRD+UoXl^5ZWlto=)mW|b)%g3|tU&qHTD4?Vvb90@ zahkL0h{(8Ia$<(uwOdj?@lt$QW64~3q!{^VfphFd@%M|6ImHf>3=YbnOs}~{|652f zL9a@Eh(IUKcUxtBGuwNHzE%;aM|BNzwX&6P2lai8hNqVkl%X~)h zHE@)x2Y>s)T&W9mmhn@Fo)_BVb#?u}jkl#{>2e9GoCKM#{xxA&uHGaV5C~Bo5xFk^ zP~VHb$ice{c4XzodHb?BMjZAD5cm6BVhc`u9cr+NUuH;9Aq5TIcA(lMhB67Qkcq~`lnk!Ck#~=Py;b>POG~(*u{)1EnC8r1K2U~VSg|8 z0bcatl|t}_(xHFfmpblt^PNUC1E(1K0bvnVg>*ny8ZN)>;z-9;-kHbgSc5qg_SXLZ zy4a9O2Dd~OL@W|ZLr^(9wInP=k0VxWaw!p!=p5BV6!Af|N9Dh7!`$z=IPF2!b6}UG zf%-gsM)T$)==o7l1tI>AdzKik&ZQu3S!<>jnZLPVX&xsQEKMwgL(cW%Cf!VKs6S@(!yY+zxuJMw4CR-x#M2gP0>hc*M%Dw`xgF}% z`!KhS5ZM_wGS7LKMi?OEGk#YbJZnf+{CskQB1u6_~f zac!;m)Ch5-l)c}n_8b=a5>A5Mq6bK22dyKG3|x;;uZ3FORE}%oyUS`38 z&EQasM|f!=Bw)};nj`8c6q!`O9mgJJ#~7jrbmBrF7EgHIFv8jf1 zQD_*RsI8EZpk|+hP*5|XhA$RFDeW>rEOU+o7>=j5}W+Kv?u=JXi6q9@EXY&a+cX>`m z>&Dha+{J6pz282tiPym^iC`Nz1Kp?(GFDnn2O_NXZdbqXeohrbXE3_B>#q7J{KMwK zEF7feOEH;ynkYOqW3)n^Sx?uEzbYMt#A90RjOe1#g2*UUbKE7`2T@Okle z=hqYM%g1UkqYhU%%*F=B*6*3eZ~Pz0PHFJb-dwPYsDa@MT7}D%`~&G< z2@iQ>Vh}h9dR8^)o1_d66n?oI2Su$b6l#G@HGgY;&kpN&D#w48&Y8~IRRyJ1JJ=GB znrAu`I~I0v>EyK+D=$%|MEreI;eOt>tWg6zBU3~u<7V#;93_MZG9lWwicp`#wB!3* z$>t3T^VhF}efr~=M+r#)QzrK95`Pjg*L%=6p5~3&FlVmoyZEtKxS-km8Gji=NMed{ z@{pP}v{}A6Gs*ClQM{6d>)@u@#NV%BG8Pk*0&}lKOCauhRYg*kD`7dZX~WjWpUwei zDaxf!aZUm49tHeOet3{}$476k`~(A5b}{Sz8RBn1XxhBjUkaB$>Q};f1*;m*an8kB z!e&hm#DXUi*LtDV|A|z=6-{ldB%!97QvwYogt!`p?;wVDhep?uKyf+?a7Hmra#~oZ zc_5o-DV=^M8*U(ZAO!xJlaY#F#7f>_9+CurYjMrHfPzGI>ovu z|K9g8sS0$1JjEVDvxl8>#X-Mpbv7-RWwh_AlvWwK`?9LJoF13#!?2s7#B%=eXSGuD{_5N zMrt0Z$*!b{81MI=ir0~OEz|jt5Qij9;z-J`RVizSube1yNuyL5L&xnK&KmIc_2k?+ z0t%qe=byBIcC#4{W7l`jrmhZ&b%_#0l%{)O2VV0KIX|D;d@2Iw#v-n?(kT^yv@% z2#`vJxA&irvR)w=ea;a9hcNl`ycv$4ZKq;t4n6Ws40|#U-~A&A`qnC*w`=S$#yUeR zWz^al#O~!_x!9I(R|$m{{!s|df`Yf-Ar)UyN+{vs*IYFD8-=tLj z!0d5H!O3ODn~OM9FA@ra*QxOSF&3(#6#UG;nEof-U$_V}vwh3u5-7m9P>+^1sTi1X zjGswiyIboOaKIRG>Z}yB4w|x1Si9X9_St%SnF;6vu3c(Z*KR0GTs7vg=ojF6u+_)9 zH*o~CcOu^G>_P`31mHpb-5BL~%n~Y~BFr+mxhXWK!0T|1qxAEycSR%WB|le84)oA}QD$uvGy+6#@c60k3JSlirKyaEJ;p9(Mq+6I$_H8NH_eS|Y zUbK(@+eLmrlTDvGBik!Q;Q<|i1{!!p@&g2irPypaEcQkB8Nh-Hu=RF7KGzy(9z)Dh z^I4F@pDqatiUP%B6dhBAKvELK+id$JzIEP&nDH(ud+i7-rdwNfrT!xSIYn@HfC`ng z*oYR*JpZL0IV@H}zKamUaar2yJmbc4gow?6eVf)g0DA7>B9Bpg6JoJG`tS=%hpS^o z6To>oneS&SwqRnZnpC>O_M-;t56lnasW01$RK4&bhY=RHnI~EVZc|*IIs57~Xe0<` zzQ}ql$oR58tLRrMj_^!zj}!O@2~`~ts^D&klGh(BK>I)BJ7;rELC$C^s>k8tD$+~` z!tau}$I9ZNpA3rtrFbq_g9{#nw?TDkHE3i1y=S&(*E$JN({_2KV+ri46X!(l_(2vW ztgG4Wrf~91ULdC__lJX&)W>)J3T*hSoY%pb&Jo_N(JPIrKmz~Bl zK~?Pf-)#sqEy9q!go1UtGvVS{&!1#3f!9`uiLntxepk@5!YT}~H8Ne(!BU5@vGYU+ za(ZOFLw6PpS=dU1iZj#P@5AxSW57!WV^xhO4nOT8B90S^oMddt59J#9*R_vs$I^#? z^9F`8jcLR@HZ>BGgHN4P_fI0U`;o%Xila8VZA-|p{)fy~ZFJm=KhE1uJs}auo2yC% zCXhC^r|gE0@XHkk|eeih#4nmx!m4bFUYT#-8+er=P56BF}&lraC+==hRrS z?}^}n?&S#+v|0l#KKTj|Y@#~2E+>Um^jo=gh1CEhOP#CHI-UC2HNQV+wpP z*42P_;J>Okhag@j?vpF*HrjE6{Fz!nODoG}sXZGq#>H;@oMVwc6+LWx-V9_(i`5IrGIiejST%OIo4+K}b7P@1=P4)DQvF0>u zhVl&U$>Feet;yz-n=`2wCP??oF+}vfNc!BT7z+9qx$pTVt-2b|1jR@ zAy5hiLf8p=fOFO`5O`rNAq#i|NI@F%#QODyEFTi`n!pAlxJUNGaFx6Srm3; zP=?W0Je7>yhJOr6iYg3{G`T8W#cJ2h1W~1ra4&>d6RM7h0R{{kS?(-qF*({3j=}Gi zuBFzngkL)>aYN#P zI6-k}Au#W>&huIJhh1h;?%IDw-BPP6VQKTyyJeJIZ62^$G__PNHz`t`b!~6;fC5AI zu!N7v?_~L9Dv-_&WV4)09qb=!^JGg#!;E@0S{>C&Sbc}Yn*T-9bBojgUl&4?eeLw#RjNugQtztKL?1kA|29!fhuxdrBUV~oXYbs+kF}FbpEHMo4uk$Gw~RA^S)brz(6-(qeoWeGOw_QK!kw@s>46e{PtUd%f|!Jp&>0Z%T{#1EY{G9NTp1@Wn| z2=Q|Zy1qyxCz-Fdm#8=kQhiy{P*!GU3;N`RAm!;rJ0{6os?1(&SkEnbuZqW}_sl(^ z=WtqDV1__5u5*RL3=N4ljqpjJ#tqE zalbc49vKN3lf15|1`)@fC{2J~l2<7yyt|+k*NZDUBMP#vR~erSVxc4hrSm3>53}jp zVvu>anqBro6kiW(FMmcbD~YhyOEW3keZGbUmc!WhEb=iV%kiI!FY0ky_MAt__A|*} zcp`HGC1{{2h1?h)YsIN@gBKCjhBE*hnLt%VA^w>B{$)ZyJuqiv_A>0MXpO@eiJ4%o zg0{gB&Jm};i#w$2QjTy(>0JvY9rxf#qd}A0sv^wLHr^jYeveFeRWi!UdXamPq`EQE zw-EvH6j`loysoMtBQnbsmSjjUwm8HaVh=`H_$2rZ*2pXel!UF^C^R2)rc>!TyMXhuE4T-40zjn`ck7ZhLw@pESSpzhktV@-T$VlS#6!-s z#q2$?P~1-(;sdu$ips3FL?6i6Qt2nFh>tm6Y#B~I*r|PR=(5(z4gGUF#Dy}(TZi%< zVrM0LgM_kbD8EV_3sf`8>E=lc%s03f4TrZ}WMtr&VFn6fSq!85aSEKbF@b z!nOv;O>i?7>$gu4Cg;XY-@35^U;#0`Rrrrjs?rb21roj)KpY`73WET)g_XPKG&F zO=xz4Ax&6Kf7lkIRNuPsHyn(Z@(ijGbLv@3D=1KfJhIXczE=o#j4O&ocVqk0u!y{w zYui-m{{%^Mt&@Si5W}w<@wM@V7 zVZf?WEhwJFpQg9B#rIYWiq&kuE_tG*kw_ZbVk+j09>XiK7?m(^D@g<#L)Ov9ngS^k zjc~Q{l^Y4rBl>f0`99+YyRvH{mZ1`lAU4i&&z^8)lIN@XXdTQs{FUcPVK0`s9VXg* ze)W$-2!fJ79F5ms75s*ivBgQ+9lK$1I!KBN^&%g)5qOfR=%?IzHZGj*nE$m^{bCj} zzibn&T&pdYb{LhAm_y#fIbjB{6VUbJ`KoRAuG?ZY z(!FUSCTI+Wy*7Q*dA8~Q?i$^acS?&cIbHF+b$mi{d>lp#pSZcNm(z>g3G=u9e<}$S zkp={h*Ia;*5SnOj+%)}pJgISl4Ps%GmWKm|95aJM4Kx0w&R5+ z0M%X#UXbBQsm0Si+U(`=Xa^JwySL%KJ1g;*zH7R&&!K$BKjs5vy7q%Hxe@^>@D7VG za(=Ia78M?IJA%6LQ%k~%{WpYNAn$)>0e?pervx*~@Pr<)UVXGVK}m z*$k>l^KBqB4b%STHj@zT*R(=GN&d&40}@w%l&i!*V0b7t6LMtT3rEZ@}kd*4ZOCE(FmEXsqbVHndI73AX z`<1VOej#-lhw~ta82~gkd0H$_nL0E0n{tMxn_|{zqbh|GQ8`5V)~%*DIJ&FjykNi570GJ)A87D3$}HIG2^qI-Hq{2IMtGT>H2T* zf+MAtR-u)OIz-kQ{NF<%NKTKAz5p9a8}al#|+y5chz_=5l$%x2zDg5!1|+S8M*< zxl$P*nl&lNGA=wj>%OIIgB{(O==KnercDtIbGQua@RBf*| zHwe?CEIT-!Af=wzGC1DT8`Y~P4Y1tcBuKTYBIkEfO6=G8R$_vV#(EW}6%PloYqNKewB3g+bU-M3X^p#E+CXRFEMd}sa zJj-MBybEa~5r5ZVw6|(r#)ehylUk66?3>ieA=0738Xi}s;uph|uuw=fjP7oIC55&e zGN7M>+$;Lg@(~0bNmk*}=Yw%-rY7CkVN%v(ymC=?pwc@*=LaJg@H@TNL@YUYC zIh1@-eDvv5S_K?D-!zv~dY|Y!DFqX$yTIY%K}e{h{tj5YEMIdrkGYxmGU0nhr$-f_ z0i~he?b3)-k7pM}Ey=LnkyBq|z zNiVR3pA=4xB9u9ta*{hsq0@lW^_R`S{c{Ei2GNT@w2rfZHzcR%A>@$jfAuC)F_xR4 zAoXDZM&9SDWrz+%m!KJV`(1Txq%_evH^L5vI@JMqD^KiG`7==#OqpxJuUk&H{XyY|^wYBt38W{@Kadz{H3i3NI<_}fu%7o6t;%FZs~J&a zD0qBRy8CR!pNJDXO7HsVn8QLGOH=p~x8>MC0CT1- zzdtkpMAH4L_0!O#1zJ1y@300|=^JH8yAmU_mv24d^0L< zLMX;bMPPQn{eiE?*1sL;iv3+GGxK3u0=rRfX>7Iw;kIiN8#lcP<|d&pHBt1Tf6WCbZ{l7r15&X9^a!7fIC3t~*hWoL7uz zTCa3Bb939IZR${EeDsf)#i~d(6JwJH~ zjJ{BRLG>uW*!+i^!9h%_M)-@-@{`1CLvvoG&k9i{jOH&h7VFIZ5)*fhI=OQ(plvS| zAK|D9zMH%(MV63R&*`SjQ&wDDeV>!8-koQj27nR*JAV55xjoPvv!DOs@&}UVtN=440qboTyi~52% zbQDjR7_~`ZR84a(l}|d_3>j$7i`hFQ=3kMn7Q1}`i&?_X4!H~}oXx5&5{a`F5@}So zFU;u>qAS-3vePKaZ^2%(QeBp#O$0N759DHOcP^d$qXQI2mR;U=Ego=8g>$PL&9+A_ zDc>WP^#3`On;+rf5ewNhI~k1-@aoX0>Snj5;YsuEmvR=^MS^f!owamfr5P9nT8Rxw zE_vsi*8Gh#p8+ztSOgZUePq8Z>v9cPtHmE%&2u8%Pt2;ArV-Zs1D4-sDlKWqZWgYR zSYYB?Y;UPBCN?S|LKJ#H!$V^xoQ&Sc9S04sP2Ai>6qcbRzH1101T?V$`pJumpknxs z3U#$5Io4aM7cU zWF-QWT4C-vk*ybVQzfjpiO27wI*?f0tDQ|o^NA)C%6!@s_;w{xru;%mmYz#W|%oeHpZ{Ob;YZs`mZzdD2~@GKq{iVHM*g_0#8OIq0Cr5PB? z1fyU88t;HbEEiKKrbc}@`cX+*ix+5aAet?@i4batu1SI@vb|f%r);fJ0*-a);)(!c zWTt>g1I$`%P~|8$!DKA2Pv1QoQ15%cE3I4Q@^Uj>*1Bh*iS$ETSnG=TLxM&G{5& z7$g7|O0}^;_ZbHpSdVm^kjgrjwDpG>VtdzpFSQm8kJtar^n2vLT+ew%3l+0eq%`eX z(q{kw43+_^r^oq*tnYnf6;KlUV4A;>~=+te1f~JA37$`tg7SMI{j^Jawlq z`0HF)BVK6{nXvT0pbQ6Mi!_pcO)8=)`2#PzEwGmZ5V<~)M`CS`tFv8%?t3JL%>s*I z6-;d~o+!#^or+4r`vifItWsHTb$nVmGL$*~Et?eXC&6VQU8Fn*8xNOBKO zT5%iQ`_-=68S0ii%~K8t=<#|$whu3iflsO8F(e$`LtB@x80KO|FBGG@Me1OB4GqN? zc&M%6Z!%I0QSdM5d1NFYl^@JecI{EqDObIFM=4OT(iZ5r5(pz+vg9UUbmb*;r2z?Net-d8tMq9{A-|aJi-|Vs z<9N?khuPv|8JCr&M9z1;{W$lY8r^En)O>!oI5o()Ns_{KioO;5wex`qZh9py3F)CB z?m{EEtZAbxvh}8RYJ`)J*c1?o74r`wE*#ElV75xAaF@KNeKH)5#L0!gfb?~g6EvEf zm^}+9L0R<_VQ^UE^(7;@?2Zs3@I2xUAIN(lJ?);|d`L-U1yH8is*{99<85jU&vliw zqVmZ~RafNSNDtKu1fXo!vMV z#0}(P239mduoQ^1sgO%}nHBYH;z4Na=!hw*o0yDpw}qnRFr;8V^hP&*GR}%@GnTySn+$MB&_drD(JL^b1+Zl|}hT7J650_h^=ws?; zm9=kVNL|Qp^lfY{ofP9G#;|iswmt?>&R+hhtN0~H$In3}IrwCGLBNd>dX+(l>k?j8 zClw^>gTq$o#N%j7uw1WZe({# z)G`sa?QetCWy%pef%NNa-hbd0**}L=7wd@He<{{rSBpCPG-=SpI(J%E_uy|M#KVRe z9nYyv77Y(X)qdK2+=h4_LsD{c8BXJAo|XsDict7My?`won{*1#fYw^L{o?e4ye;}RR5-TNk1!O zY1s28^vlh)-(U=pG|t&5P-wEWnT#3(i`#U0h{7C+bwWV>GG(Ya(Y(ZTg#2}env^gG zX?b&B*1O?*9m<5thL3@6&91`y^mdb)XO$;O$a)`(tup>rAha`03HDzS4!O6;b_~er z-sf0I+um69q#@*|<55WMiD_0b&zZSu(K<`>`$}ueXb9?z;>DN`osS$J{qRRFOW}nU zBSJb2lzBkwBpJ_PQVeR40OyFpcph#ZJHPz|!z!AXtRPCad-|=U4vB!p*gkTZ9BDE; zjIEE9vjBpEt6qndHT(PL-xho;LooXVVJ4>0&F4a`c+}me>JB&v9-Sr658pS4TRQA^ zIkkOHzL*pSXIQ7`AO;6JW(r5eTL3sSAL}5PnJy+dSvk>JYz#{%sg6?E3elq;hdep< zJgLqskr`Ew$1S}$TJ;Srj@bXTUr(bXXXAg|<$@BozmM56S*PUFzQBTlJ~wTmg?TLg zU&C+0G=czJK%>8}$E@W?5LiY{wgkd%WS>!8u(g+oZMPR|asA8nDdz# zK-BZ5ob+u9&eS_>Vw5}cWgJIV=O#$D;x%vqhCoo>(4;_|oeb%}z&TEJGUG?(4@@!# z2+$1E0m-zhN$5G%U0h-jBnw2*vfNR?t6o|NmqK~cxw!B(eye2s-#uw4x+o+B8y&Lw zCnUkT>%B=0S58Wp;ol}CGt5|y89zsX-a0Afmx-drBiFcA16fqTFak<_s%zlB(w;)r z(6NT;O@9kUum=cl4Z2K;1wR}{a>-zfkaEu+=#ulUF!l>+|B25`Ki4=Me>^#{bVUz~ zn}o0;24%@hyhC<6S6j^zqR}?PeA&E0(@qw%w@?lhmH^#Y>-sRD48^AlA&b!Yg4Eku zWetauNOS-hZfEJRf9v!o^0;GhI#>MAHjJu4*q}LH2(KRV2W9P2ZYOaAA;}NNvl7q= z+L;eC88|?7GQpg83a=`26RJ?0-;;_>3%3w4pX{(g!KQX49ct4P$GwsWF0@{1g{_Py zLaq(IqUmw#B8uA+A;Wea^SUc7R#ox%ODjyq`IX7ztxe@VEEwZT=KC`5I6w9#w2rzA zcv+P}L_g79{Q2V*J+zUbyk!Pvj;NQ) zr__~nf?V18n`C*Z-c`}D5rxH^eph7)b73T1h}%nXS^Ni-Y?&Y zW=2fR%YWxP=Gc5s)gVJ5-|{=x&<#b0st3N~qYT~;9nn^qQzLo)*(96Jg8v+SGeM7c zc*SIgmfn#at*mP@KsYma>H*%g*<_A8)51k)f{F~(Z!+5azjkC$0`+;g-W$|p+O+*U zf@LX$ljVe!zTYg^<2UAGrqpYpo2MzpMNJvK2cAU&r$(jxI7MHwZM(ur1`y;VIbK~y zN|?96tOddYSBf~xoFr~&PGv3v(9@5P?43-3dC%;6wrt{4^S*rzURrVO&kLftsC6R4 z-@>!GAuyQ|HH+Az`9m9!$V)hu-LSt2A8%W-FEQgS?nih>r!vmvOt zi*rZgp@;N~L4d*q!Et#(B6;!OPN`1IHRF{%sM9s8F*%2ac_9+|DN)OsCzrWg$jYPm zgn7`nc_11X)BDz_r`Jv5p=lRX5eQQmK41)pM-gGh)R4pG6_Cf$Uz7QT`z|ivQ)bpZ zI^x54GVLgnPZd5L6fTwzan>8>Fa08(zZz{=&sHcBsg5rR)-ym~YyB&@4 z6TiNk)go#|E0KklA}P|hFtb|jSq4NZ58p`cIbQ;0KozJCaDb3pX5EiNmAM*Ehc3Du zEw;LmCe#b4b4(o(ln3*&SGUjer-cABqK;m6?B~A+y?0lO>=j9|hif{2~J`|${zBJdSd zk6B4T000bHAR!8rrH+!vBcPNhWeOM+=Ok?42?Kg)bF5f6<#HHJ$qX(Go()7|5~{}g zRS0FjRH!{ZeXLKfrVS%No%G2vTJ8@vCKG^W{nMh2Fg9OC3Xp+dLedjJHhpx#$aN@X zHR$|Z!Fu+7!9{o2pTv?y!(5#Lt>4$%oa5hwnGwPkE$b`Psf|91O-$K&6|H!P4e#yI z!P{Qe`CiVGHigm;oR@vJ+}!3``WB7#*RaKY-58@uzp zzE#fVjfsLOyfj~)qc2JB zvPD>12!E#}(5AfK%=n+@MSr4qv(!5Ucn_{qeCCy@ErW$^e2Oy7f7d4>@Zsvkq!BYZ zsRjBsD@0Ht77}4Ioid3rvU=HKU38IYM@dQcSu*vCa-(*)qlRk76QEd(Vas0S9-aSZ ztN~S4P&K810|y}rl=ZD5;X^2xNFfRLD-0mM1`uO&uzInm7RM1MIixXYGyWtT_w9-nyljzn#$iZ z27$AyW^@qQutY3-o~vrj_!Z!xB;}S#9?v@LTzDk9UGG?H%IKyHBId1L)z9Zq=V~kI zUacKo2QUH$D z^{3}|<=AL31a%f9jUmEt!wHh8mJUiI0|48Ys4A4{L5V>sBTc#O#9^XJi0InXLTe)B z_>{ht6yNHKPUX(u&_&95=M{zl5CmlbbVTB%6fUyYf+0H#spZ9rZ#j>`qB&vAx>B;&sE3II(K zw+y5ONyKz>k0AqjZKtv7T5|r(-1{?fumkD|M~ZfJ{+@;nV;A_8(o<7sPs19Id7rMW z%q_IfyBMqcR}L7JPUF;=U(SS-mybj!tbSMP57vAsHPWV^f0e9K`qc{o53R`)^*5n( zYRQBPJVz)s>7~iyneZvouQfNueM&pRP5@Ki#V_;GJNCX+l?{*qLc(>{hah&Rc!&GauIPM$;S8v_=gbC%05ytKlFQL) z&%n=ty9UF(_nsRwu{|#WxSAnvhYzbXGPzu=8dH}zJ&J= zBI0RG(6{D{XUZ(rDw8K0szO^U{`ZPxQ?p43>r(RI&}3oj2S}{FMTYfKtC|bvfw&3B ziV^0H-|8G2+Ft1{&6aAwXa;ib`Ui3(d!RC5|AGpW&4L~&aYIhTBb#J;E?L0n(Q-f- zK6F!kA06M78~m6H*j0=eJ-RI+Ad2L*VqtIEyrbEh^4U-2#bq#0xfKQge29&9Cks+B zJ(^^~bO6#k)cqh~M^NEuFp_V#^BSQrg8r8Jbi=}YWx1ImhPRR}^X#SR>UYQ-uOmMx z|I#JL_%C=g1*urxyQ>3Hp4*1jSIhvTaGg42}TAocn+pY zc9Od7n5p?{^gG>^GQsaLjx#`LzG4XRz$sMYjxj8g{97;(*T-vJg7E`mv(Be>OL9TV z63Q_Jz8-R%y?4mg>((wXSr%nSvb%Ex!JVTCl>m77Cg04!eoBVM(K&pttAIhu;zG`#DjW~jcdDh_IO0Dc6))OmkA3a0HGu&s; z8P)=x;dx(TVAMe7ZNRPFYJ@sG`S)~JBEwiXF=3MC4jEoE{*G3^(LRuY3Zzx5A3xJ-}!{Jc13({h0Z9palb;hxbm^Ft0^q(o>vyMq-(31J(~|G?1hBRI$!Vgj=<8@ZfWBO=!9S zqhyoTQTF$CQG*>DwA-_=Gq}$R3xcr>!2_~`+R7DMh)?`kHp*b?hD=)7i9N?QaR4zR zZu$Vb5+2U7a(OmhQJv5@@V42kX^ zJ-{d}c+OMmG{c6<770#AQa+ZNsgn&MQ0iiqd$-6ho6#HoA2$ij51k=*NsKYq&2?+& zk`!By&(Yj>ojdhsqsEyrW3BV}9jE#(JGSxWytDsdq~(fmlok~pM~_Fknn*QgvS5I} zqVhq&(Mq0fiBOJbonLxs3c#dElDPKvU^M+~iy^o3003)TqQw51tvHX^ws>YGw={+S z?UC^fK0hOg;f>-@i_B;-9+SaQ!HoBr(5cjiQx)KF|s75m+}X`aa}0+Q-h<6ML& zyp~*qGu8L8&z0+IH4}@Juaw4*TEI^y2CAWI$h^k3WX|j<5{_VtC_;UnqSc;aUy|;9 zMx&@g=!!lsACj$x$YmvDnwYR^0V@yTbCb%u?S;5>=dRcF~N2U_Kf`9X;Y z6rnyJn_;Rp$nA<6bME6yudX_%TsHK4D5|r2D=&BadhEBf;PZ5J;kC0Y4^G+bLt)X7 z69jRAIJQc;e3Ez?1lO~uFYedJq#UoY=@&=fF1L(X0H74P++udPYy=|}WZknI{WF2_F~(WgiY&a$KCAZp|D_p9MLR0wpJ|6^J^>@jd|J_pLyJ42TP!DK4d}w zehf4wc79U5>KIq1tv(HXjZ|Vyy*Kc=pI6k>H4pw}^2O)vUYU-YK53GDT{1aKnfVlg z_K?eZ*$ENv^07)}L64{0GPZRT60E3ljlsAP`5v|yfNRc0lC>jzKZQIP)X}6=o2^{K zw|KW(XxlfP3K|*B%4e#-fNOB$c}U9wRD$a%Eb^$xh4k=?DwGl4V}XS8;w&Fj^pmU% zwFXa~aI{0a+R)em3yPyo5U0;~TgKjWh{hx9v{kCFZt}`cpnfM8f6PX^CG}p1mELKa zOS`tYNC@(3uSlC2ZJzsGsy`u7Jyrbh{&y&ivvN@OdkR2AC&&j2@S%h@8Rni=>!0=zV>m{=pdwRVV-99pATwFtpeZzS$ zLBxh?luQpxG#Q}4%p+@e!T{F)c`@H;wm&W(TzL6jv&H+oLpn%en70DCZ$JF}!hq?^ z7jfJH3^)Vf44n>n@W%paxC`h4abjDqAnrk*K_RhznUW{d};N_Y;rmBd{fe&%+A*Wc?z@9B!xepENih8Kt1 z%l3@;tYdXIaeI z7j?A5KU{QyDltbhLsPF&QSDr_6DR)Z2ZP2%;P_7FCq#%H@oLqg)8YvDOEQR1~^sV z3fRa3NkcEL>wPd#0v7FWk)m^rrb3rWQtVQ&u4@I12kE5AASEKn1%N=3DPqw75 z7rbU4n45otXdRpSg8{@v8|!XqrTEw8;Yxc5Z=oaY0S;vg0i-;fCC@>LV)n+;Hz%7R zi@4WHG}n;-`Dqm>fT69?)195uzL6@1+YA8$tfXB$`_$6AGcd52r8Mey4Kkoz!f}&Y zI(yQK2#&CVwZBrSqv zPZC`kCCGV|q5v5r@BRV@+~`jU<%pRrzBYLpve)&nH8{kO(tK=?-371}^xO0uPYFW1 zGl6A%$CTG$wL+tAIa<}lfoF8Q`rI~QM|U8zefCjr?ar2_qnpFdrd0QdEyk7QgGNe0 zt2^o!Z$%2nbpJo}Y?rfWpF|U_nu>0ko;!rm06C;xyyp}O@xxX>sB~x(O_ANIYkL6I zq>FRh#KUpQ-SFV*<)kNqObInNrre6y3t2)=<=#h~V-TfuXOPLt zWCg*P$LgMQ(9gga{D+@h!IUb0e_UPUVsuKy=umcbUrgoL7MdC_v3PZHVlG22yO!6i zRj{`@IVjQ!P5s7PE2kcyT^`ad0GHr_Mr(P)r9VI=&0yNp%BN3gD%OCxu3&cK&Ni^$ z=ltuGTN4YWgjYP}-JT;^VjFJ$TA`OjIT(Naid+bsH$cef@*G}G64 z$%EsU^`NMsyR{dQvgk&d4pQGwk9Kjs*s6QcF>TLg%N(Lv)%aIACpu9YL6z}a@)km`{gv_xmk@5SQ35p3tC8APjFiG zFt7`_GCXv7^+ch^<`urCsBkeq$AZumEN97yi~+ID&l)bW7-j{|_7XHO&LG{Sj9OMl zfAagb28A%$%X3R(99YH7O=8*xBXECt>P&A{PK{?BaaLnGW(X|Mzc2Y-wQuy_k()yvlexYpzT{X@cD-UaZUahb6G&14CoF zV+{@xni!s852BH1UPIVB@kT~E-jAZNq~=h91ws3W5%6_fMTQ>?1zT0yfYYh4P4H3u zTUXIMGrR8DZh%0o@fas*VtJ{SsOGL@r{g*7WV@NDj70de#8y>1I&NgUYc#UxI5pf5 z=>MbqrWhl+vDze~ZTu0RZ9}bmF@uPaZ#BfYsXCycA; z6g3*KC~7G3-acWIKPa9i!4W-(qBx3n8{CU3%X%#MW~mkv#h_04Ea@k(|y#&rj2X*MRkD3m|EnHcS=dwYhaNI>Ma-Cj$e_eHoW zrsRYR1;1tuX(U#JE9ap`4kU^vRy-*U9!3`IKu)qly3Z~-?Fa`Tly>Zj06Fwb>8z=D zSS_||8%-v)|DgX)$`cYYXo;WlBy_&(k1=$LO}(lNrv zkY67*Zw{f{ShB5+^wFlZHSbYF?Pn*RE;*LDFs|5XN0R86ak<9J?}bBCvefzfi_b!@ z(zVeiTaY@Z$AD{Td4jtnP}2b|;|q_^>?!KKmr3<2>Hq)^!2uhHy*imVcarVKM&kUX zUA@}|XtB@&0-|W#GX)!-2G=%6fD8Zy$8s($M7a)C9v-k95B9DBEeaAJOK}L2Aqte; zp^}Smp;#~!69onv)gdzO)pDtOnSAvs%8a%Ps3bEP+!*yLIFegBYzmN-sA>g}Ua;Ud>B)SON%T#U{a) zuu?EQ#gC)_0+$2m!GK?P znsSH&6u(PVYLWnu*{RPM3n1efh=vP6KXJGo@>A~yv=fP@egEGR$+bHe=m%y3L$WDGCM@FSPL z`g$K{L0uX=t87(kp={}=YsU&xmhF31Atf)qGrw6vF7f>eXhCdMuOZUN1XW)T^Uk3W53flki6Z=K5zx3CIIFk z3Y6`d43MC(P^?55!kNB?Rod(ftq3aI=ovlsHj8FZ0`6zS7O`=Z4AkED;V7{*(rl&1 zpg7Mk2#4O0F_vTZG#=F$PP46w{XO#px}vo8=~1B5 z>dVzY4D*Z}@syB&C|k4gggIOW5R{vkVMAYaduuhY^Itt|~&{z~fVQy}Kuj*@=Ym$+}E%6|X=rbWuQohgs@K#>_DbpUvJHAKrI3IacF>;=)JHt6 zInMVBV%54ktbMxnjz|xF_C71GgyE;$QC;1)88J8~b0I(g7`9h4{nH?&ixGOByiR2- zCseITx}K)aJhzci?WgBWVu1Ko7iyI}*`Y}R%M|1{WW!zosk3$blOaz0wna0l2}50V z{MY1#ZseOw$nA&}>OcM&h12Bh?$U>;&*LZtUw3aln9T-nbUj_b*UIo|Qdt*?A)=y4rl>LB|()fj*sForF)M8dSG$0u-yNVwCRxS@3Qv zj&B1d-_r9YAKsb2tEvZk2uS>%3A`s+Qb`RDTZeFvt?E(|qEltPN|PPircO@Guj4YT zAFTmU`XgzR80-CAv!6HMMGN0`{}ctMROd?9-y%&z&Vz>DK}On3Ve7@>8|^L=DT`f` zd^>fdizj!t-g_8yx1=KBzSk|q+NRKw+le$=rGh=ZkARp-yp;BJSNvlK=DevjE`}x8 zJF8H7r&ga_N0?PwD`4KTKQ)gR9$G6&U7*bC`m#4I~7CMV5h73)r}Dd<wzn?*6dtXkW5G2li;oSOxEOxpF&e!ILb-N|0lWoDWBR@oJzX>W4aVImhLqhL=u`# z5O>Z+e$(=fnc(zt`3_02HrYdbVxIxRT=nn4JY7dsAUK+ih{ED=UPMf6fWWxcH>mKF zL7VWM^=+qb|Mg%dtL6F-!C|!{1ATs=kL+?6QNcv;GU>kw`%vazyY$%}z**NZIE&OC zsa(wKXo~R1{k^hrbn+2Tm5AP(@*3Ap8vPYE50hUr@yXq9ab55zLqy9@O9f|F?n{g@#QLhBQfwqPQFKwN5?|p z-^+beHWv#Zd>kC_OiJC{ic$2+i;6M-vQ?wL<~4~0pW=2Nt;`a)_%JF-`FtXy(EG*) zWbPupygwKM4VcFEo++)vV0Ni|Ic0(Z@3CdY(E{NAPDm zcjIR_5F^BEil9b5LRy^D7`VA*t^13URIpyO#jd;7cu1b|`r zC#L(d)|Xs>)umJuFebcnJlqcLHc?yYUrpVY_))pgD8#K9aIY1^6X9paBj#F@ooo0mfk$e?b%#i0y z!F~?t#R9SUMu;IzRWwIbY-ZD{!rJHLv-8qgx~%i^FJg@sMzA9m%cgd{o^ij|rBfA( zxRpPSl_ZC)k1E9_0c>f0C+F7eg?j*4(bj>zqV(I-9rdAUl---5P5DC*<}?s7C0~0D zSP=mcRrN{Q)oOr`;qS%c@g;GPfLBOK|Ehr*Nws^!aJ;lww2|%m$l}IpnUE{30G)cN zGKm-t$!QF#m>$lp3-SC_JBP1(bBWLF>g~a_Of;UQiQeKwVndi6!ip3fFl1WTq?&p~ zEtAf?0d+4`&n(5=hm0V~an(8q4b{N@K#(wwhF&{PEvBaoLI3>?(-;gV05{T;7CvWN z$-43)6(C+pzwm1pH8*r0n~ecqLk^%)Z!oNfVej=S0h>Q6{&DQ7OHiJqY4hhe$_f+o zQWp{ty=6O?V?Rzt?wdr^^16pe%OiNl&-XJF%}sS*8}Uv0dW*W#$na|<)OZb%U95Y- z_x|;js=BwQ@2Q)c^hzDDuby%K2D_><9qkhB-zhl?<&xm~UWW2re(Y>uDY}mvFR*e> zR0~Q+>h`erWZwGf*&uS~ahWMI0oNPy3Pav?RkZm;(X%H@I!}zoLg)3KNz`Qsl}ntg z=0QJDq)|-$XzGF|nmv}MY)jMy+OQ$dq_&i z@^z!Fv|bhiz??+G%(%HF)N@Mr8Z+f`7a;)kaoi8va*HBU1YM z)^awBBrKMGJt7KJ6BvCZh*>wPsy4XEd>#C76wmfXlAq}29b&av>F3KWQ}s!(PwpI{ zAEe>7LSmrXy9U?zgY0m&Z^_F(0(;zyqsA!pYYI0YflzYHt``?eb5t!;*$MokQh2Hn z_|e%WJl4Qo&yCVGVet~gS)K`HYP_OB%0gA#+?1%_#>Jv^$qD+ly&8mT04$<+n7mVA z*%+kUDD$^8ZkB4ugGGeL|K55jEt5vv;N{%Pjx?-0U+llxVRg2sk7A`ev8@3*6cC?cAq&Xu_?Q{#+)9*S}Y= zw7%hYogg{s3;N^yN~J{xv>nT;vYcu^JBQNE)Tq^7Jj^N@4`s=rnaq{z3D};`I`sIF zfV60%piN+wUApH)-OonQn7$UNGFBw|Sl1Gq{Ih+@P-t4X0Ta8LLzKU#h^&Zt9hGMh zk7KBbyZq}k{}BscfvUj0PuxG|P#GCd!e#uXlq~$Haa?trKu+3CxuCtkZMgjw7;YIf zZIwpw1_C7vKWS%DOpidx1&PVbWsQp;c!Y_L5$6f45@d<;h#@Y1geB|3*5-LPO)Dq0mxkL3hEb1`{A268Z<}) zM57K-2@i{j{q2B=cawh`rb*Mj3hYSZq&MGtc9B(eXsu=(aX$l@S$C;1@hY*i>Ud%c zPL8rltaTq(q`!|)6;Cy~UDCOvcfK~ctze-%7;6ejv_^RSGQbDJiWsm9sxbsIGZMhMe4h9XDXI8j0VhK{S}+;4v!2xk!FdB|9i1hAzUb>~RthrF_d6n!Vp+PXO2ojw z1>JNIs=}Mt50~>!xDchrQ+F=Vz3%XF=kd`EH%=_Lw5|WP8$f%2244Wyt;01r_nP)v zSKB4wl=CZ}>j1gW4N3=|)eS&f0G!E63%+)?-WyBoXRf_2u`*9eLx04RGxtC2u%83gQ7=+`UYa&6j4!gA4Hve}r`KuTIV!JKj^?}{ z^^sZuBN%*GfDH8M`gc(W^)#WkIbK-NZhXn;H+3Y6WUl!|bn7-%L64Paswo=HLr_v+j*KWo+iN{|GwYbDD1f<2`u zh}P!1P?h37r~6H*t0XcPVVf-m3bH3PqL$ElwP(D|%W709t)4}^okufI<^1+hgu#T`j001RwA?oTUe*gdj02EI-{T3)%L1wCTY|B-G zqKn(c{VZjv2|KP-=SwklaBzk1#1Q9x+u=l9Flb6$5qP6k2~%B!*;>j^5cQ#XMSv!a z^tt?zi-P@@gWc}trwu8t^-wbiE&}f%%9wZM2>$`uaol5+VFm;S`nj(Pr zk0HULb8|AULB{xV52CXdr@J97W_dW-G9e@j>AiF;mUTh^k%lumLCsqAs_r7BDDe1m z9%5ufq#CqSoBnTd_tB+JTwHHR?j&*rb7Kc_Y+F=w^v-tjp$>vTeG~%^(p|28NyP=+ zobP1cc19pI2`8n&g)BV0#4{Z{5*)IbKyeKa`?911!*9>KO?6YMHISVf+3<9mRLI0< zbfOB1WVt^B?_S}Y6imd25pDf;g$ae?Y^}{|Cnxzu~r*;(@tSfT_U0b7yxeDcyk~RRV9d zfS>s9v>Dd!WX2&UtKNxCXxBR`SfL7ZXufcT%@D>@zk<#yIe=gPuF{_8^hN%>G_DC_>PGG8F_u}$GdT|>IC#gfK9a*(R6vdq zH1uY{tz8>imsByzSd>1G%5TzrqLgBCR}&aQ^|J`k;4pN!rIIV`(mO_w~3N(eZ?7d8AxNVifEOFgW`{wfh0tVE^N zHfuVdh{76uB8=v?)yeM|*cA{~I^txH2o+@-N3gBh)>Hk~3^S;CJtZcMu&%d3_Qor9 z-Wa4w%LK$!JxeemyHYZ>7K^*-f|##=YF#SI=j{?_W@2%>rledKha2Iqw<`V)w#BX^ zHx9?9s;Dyuy0JA1tnYtxgvH20^oy0DMhe7^gUPP@79^_x++TyYV1lm6AiV*XnMVGU zu%lh9Y)g0q@yG?Vh^cL-x4^Z`I>d5}-7RktJ z+J~%GjovA(udGxhGJFaGezB?0rGq)n@HI;`yhcYbD3b=uzfjCLoF`Z$rpo+lJZv_+ zEHWEu$4@*lnv<2m>qBIm2M{`*{wgMpi{=dwE8MR?b{SrSyLJ&j4{C2A!kUgxZKlAF z#GdbCo;o!UmwztXgCHpI#Ai*1#4d6S*togTPg=3j)&(&ZXtU*|rn2UrXOsoBNnenZ zEZWcpTdtIt_7=2HwwqQ*OqJ^%e74uCb%%b1_bS3V$5EuLlt*MkFQMkncl~WIWwTNg@;E@R zwk|O~n`?dzA3-Fi&1dx**Xz?QSde?P+bxd^t|QMH=X6M_`8ESLa4^QSU^C-<&~C1n zsf#_h7(rP=dTh!s*&g{;aPCe2^_Seu{I3=kA(BJj-PYioE8puzTMV-WMsEx@WRR=3 z24_-1@H2F6@MUF%i4!FvZQ>KH^L%eWFO;Qvqn39)B((DrrHES$kMnTc&G|C4EZGPv zoc@4>)SA#O0@AJUF4VZkA_3_y@>wy?gROvr@_h3G=ZfH8{mgj9YR8k(6ihV>$rPd#{$oXg4+|CNqcGTu_(a)9H(ajv9N5E+U`nfv~Dpy zVWo`5M`PpR(0Vu&cs$-pAty`Kd2`IJ`P}($+&#JZSz8G%BKww_A zRN!Ku4P4`HfcoG8XO7X{=DK@*g3SVnHth4G`>^^TihLOxc19QG8TNcmf<{!N3rJY7 zbU=BfGuwzM7)lhRcTN-ekO#g}C^O4^m~kOSx{q|a?7$$-*;_T1=mM$waXBh*T7~ES znK;v{L6+YC-%B6TSb=N_xD<{UoJEs@7oe{nT2uYpHi~sfvh8) zFB|Yu`*c<>!7$&}rA;$j^P=qr$rz;+!n@|m4L?-d8oID#Z#bcSC`R12b%JNKh9ko? zki@uIiKUe}3gv4orqpOn@v)WNugeH&>xsuUNc2)obngp!~I;O)g)X+0vzy))g z7Ub6%v7kxG4Vpd?g8r^3Vb;;5ffsx;2}!A1a{BXK1fl@NI*3_8%7%`PlmZ|SM2?^n0+zP+#ewz{nE!8x7g}0 zE}jHlMO|(X6_tG$WO-#sFQr%(nZfov{%3JNe#GMh)Jy*C>)v5rMnF_Pb@WV)J_~J5 z-?P<1l4}GjIiEa%-*LKF9uJ~dSxY>5Xv(|>Ljrm8jMr^fyd?n$c$7$UYuiU8UUz0-&!+BRASK@LXI^ zF7U7ZyC^)_^})f3rs#E6AN-SSq6rA9c~yJeo)P4Ee0c2I*tT9>st2G2kL;sIvl^UI zc8)mq)DKp|SIAEt3SDST#!`Jh?;j-4&QdnrRUq4epeUAum_<`!IO;j}*>6q&#;cP3Yf8nc{@94N!=NF++YH}g3JN;z{IiE*EF`QBq zhMEH!c1aJQGzMC?(p7gc-7{G@$#RmzLkDj$cqpmg+*24B^zi|dI(q^QRwHgPSrW*l zlqyMDm|H7u1`*GEkjn0Z7{fVjU?;t3x=6TBd{10(5o)4Qp5o`yK8ep8bnpCKb4Y^h zLUZC6?kUZ|BcjJ(*o{UeA0fr0@3w|~zGR8V-^W?)jF$wy_9Sdj<|2z;TA>F>WuBq=td+o_duf8qc<@S+_3Ta->&bgR zZ{@Y(k`o>y)$TaO47ZMsah%ge1Ft~>D;dMY*uz}gi-YHmefQg!S+5^VdU} zN;)zMNjGLg+V}Yhnm3IDGGIWO&O(A^t_k#7CV&v5`UIGQ)n?8#S?yX@x2kNwwQ;-I zGre8@yXgq?MWrO{Zv597(p2`o@%ZBtv?6ITyaR*V-q$-^*`Yv zRyhSasQKC;6vNhaNI#r4CsZ`5QSSBp#EAFqEEaLS4x&EuB>xJ0>~>00Drc_G|bkECMy)K^tB+*zDkX#A>B|cJ}Z!|9T~(8L6kf6VW~NE$p zInXl~E!sqxRBD$RPCGCQ>+Gg{5oD9T&Ykr=JA^TZ|wGok&_gg^p@RLgn%*dQrhHMV7Y6SJLS1PJ;SyFS+4h%!r}?E-?R- zu(}t18adLXS5I*EIOi~u-A?~`Ii@$&w9LY+1OWfn4rD{c!m)qDK&~v(D+-IH8RZW3 zQPHWJm)`WyQ1#O1vKIvX_kYV~Tm*jDt8nc-Yq5O=mgJtIjCOlsj6gYIAB1ng~%9ZsUrV0V?wwsWv?5BD%29WDFX@&Nl_TplXK5Ho zr73$SrzlD@-@a=X%XbG9@LZ!$Dh)bXP>P>!b)~OhA>(hy=!Ad&?*s^3%ilat8C_++ z!kG*^!n==~b?u#(wi$D%>h^0qiHu@ylcMh~RFxy|>QGL-eUVP2s43ly6vjU1iC;!swgGU64<(RehU-a`E2S|LV^ z5!qwHIlLrVUAoz?yzwC-YIe4RlX>8;lYi)OjP0-FP@;0x`U?A_{a0UqCz|o&MR%Uc zHr8=OP@o*-O32w)1D2?0KR@@t*1G zF_JM2N!20DqT(9*5}w(tuUe}ID|%BKp~vb4{rmrrByi#A@7N3K9o44~2!haI%fkV6 z0RX;7K4$fAKYUCg07zFI3hxAkBuZEih5Nqm+9VVn<&_jZ)Py}dHg9^v9H@#C8B#c3 zDwQUlW%93B!b9olb{tmM7FT^E+IxK-**567^=;30A_q{f?=$8iwh-02Ph|X$bYL)s z9Bn!{x-~ZE8j0CQ<0Fp0Hhy8PKu;#8X}){Xg84N`B)+b_P8>nZDFa?oMS>q z+2$d1fVOCP*>i^A zs9}s4rb+^U+L}-mQ!-~fN-nJ3_e<13`I|CgsoYe8{Cx!6+mo2@TZai`8jH#O zfo#_i`F}f@om>(`RPm-jx!+}PV8N}fl`4Yu#MyxRfWZgX${jdut*PEs+gYG6M&nb) zmE*FdV7&k)WuL(3@QO`xgdv1gN$UmhhvanP(nVoa&*R`zd5tuE-US{~Ey;upS*;Zz z7;QLGcdf??H+a;;n0bGbEr=>s+yTFm4HqiD))#aY$6~6o z^NA_p9116+sWCO_We1-Ax1VTzmR3!_oGsRyIwH(*vhf8Py+o(3F>xc`GP#M6HDK83 zIoE@MW0p^IJ?qTrY|8ycUZ zpyU(j`j79M!dF@2d0`cuQuVpR((>oaf(}R7{Z=~Y@I?r*k*;#7sFi*5QpHH}w9fmS z{n~MN3j(VRzk8vx+X0=TJO(moI&ye4I(eZq^){ z7+r!gcvi-_Bg}BVwj4`~Snw{5oFEX0Cw7DxX6Nlm_D^^>4)4#$Y14K4(rN!a40Cp1 zs*JP!!V1cwNm~{OaF=Ke`3+E11!=JzN!S2fnpn~j8jnx2F7v|Ggx{^$E|5HrS}!iz z>`s3#0H`hY6~-RE?*yvMt-6E}^E}W`up7xr^vZyZ1%%3kC$~RMDt9J+U(tdII-P8# zGylk-h@1awb$)u62&Cx8|4CJHy5J)fBUAaGe87S#rP^0_{~%t(f9~w> zKQ3m0HYeGur(Fa;I7Y+h1VF=yv2t9O5aPqPR;RiY;DfMkVM(@3eB+hj%VXrLZmh=j2xn4fWgM zz6(T_@qkF7ju(oe%U&at$(QtueGH*0h#%h*ug|j8yXkr77%gw%UUnQ1y&~HHU4~X7 zlAdPd%#*C<5l~aXISca_9aBi5bVhoMC#;f}f>t?z05tU_2Q;G}8b$BKT*EVL&nI*< zrCpXU&!VjQcCH^)h?mGm(eKk*Vy5Kn`}f!>dZ?ez6D zXBv!Ye)RKvf2cXv0i;C)!FjPPVc&$ueC(k&Md216xiXs*VX4`u7M&a(q>bRrb!NC? zob<$zR|H?UKpSzXMPUxqn}Oc7@{DihNGlJ1eVt$wWCr=B+UvKx1Jahe-qI%*ybPvf zQB9rzWJ0e8rqUfFja=71w)J=eZ6y*g(NTgnK@DHpu(Vc^kelvnR(;!qKUU%2 zQg0tx2*#C8aWVCVrj4vAl>T|Bby6MPQ=FllBp}^-#4p!DMO{4$*zznmJVb_!*F+w3 ztTA!2sUB}^hA>Tz{b1EQu}aQ2BR-1RqQ>{JTPc*=VM$iDH~5;yKS8^Sj%Q|V5LZ4TbsQ+bN6#nk(?34sL62`3v--TgGlLRFp44k>yFs8cru zXiiFR==ExYY#F*I9`9nelZOQ1B8KM=5Y8SDyqZUYstY~JkfQOD+{%@XKP&e#T^X05 zp%)9^*_Q5TF1SjR^2cKlIT6v;zsoE?w_8Z$AGo?roW)cgws%?>-z}&eB76%Je5ALX zr~ZVN*hHKvn*pW9)DT$5b+YT4MrM3dd{Dl%>YS}7wsb~^E`ELK{k4`*lcy?8Z`pVI zOMTtJjk%EF9*a47So7~R1!P49zFkrC2asDCkCkaA&p;bvZVg3}PbZrSVOP2yrSA-WBejzBC6jg3v z*(#an8FZs?Z(6Q^-3B#r?17T(7ofVVhE*}}rK^c*d*o(R7V7rx5Y5k;hJ7pgUgG%8 zlb-h4P~jLvI9El&>9tK+H)TwsVUC#Qb^pBwv(j1A`thSqg=NdJC&JLAWb=AN<}FMP zR~D+8@(9o73ZBvRfh}r;lP#6U1p;Wz|4MF&M%G3+c|P%>gqQR5xhtIb6R9>>vNKJurN7gayirunI;*lD%IyQr!<@qA{LWNZ^YlcO$BJWVM#&x}v40|& zydW`6t#f#C5?-p5S{gD?=`WdYAobuTn&#>{WV(}ce9&+cQW)oLBD}EXmS19e_u=YB zVU0XH+gc(AWV@yYiqed8K&WV-(hWmMfo}u*Z;ROd3dn~z z%%$)W>W()+(((mnot~)IP%Z#smRA50Dl zwg;{z`azHSye;*Dn4~3d?!1B_=@`t>+>%j7!S;3sbrxT!^P&PaM7|XdEiG~HDAA;> z<4=+lm9@I-0WiXVvnrf?tXKe3Jf-nGDLa2N>YAZ=sl1TNC63R0aWX48_b~fZYAMiECU)cB9?}%j(2xrk{S9+L zE^^PTXnQ28@kY)ZsNa=jcEvl$++su!9rqKpL)lw6Cfp{SnHbT=1gZkNl-~PWQW0q3 z*R3N;?49Zonrav)dOF zTfF9`AEvTIlWy(D=-%EGxe}68nd_L~FKnrcL(byzpH5)`YG7%=Q%52=61_q-aqv29^| ztI$n7#eQmsAg3l)wKR8&Iu4Y(fl&eN9YCyD&Nj9EfApN7W00vKJ#))8UL*?EDkfVH zzts>K+AsU1DKZ5g6TRC4)=E?q?X4gwJX>sU0EOtlOIJVDW@(pNM18ktS2V=fIe{d+ zB09vfN@tq+$n-INj?!}W2MVX0wbz{~MJ4;9cL8H)aT$huKAod5x7Mk1twf-QX~Lbk4mb2m)Jh@FG5;X&qQ44WB!>$1d!)Q zamnEWX7vCfVf^sq|01wL;(yI6FV?2QSxmGFAZd?&oK`$?#?vO(0-qLJtoIH_bvdkO z$ST2=ZR;eBz`{aU$58w)BUR#_7){#&JP>P+Xy@4kcq>;8q4Uq#KGOP$ ziB#8=mFTnBpB2)5ujuNC0^23Ta%@I6EE?#A?B6#OJD`3FJV6OG`fV$wL z`D^2mpt$nd1v_z5T_g_iznWCo-U3WpO&?1-0zwx}@#shs|3#nz5roSuuuf?9_gTLH zT4mmK`ZXtCWmb+l5l;3tosW!>&qPD(9%a`?N%u0-&ZO>!=$_j&w!q)9Eq0{^P^MST z(E+u|hxky$^GOnH^N{C$-8M(-_wBHu$YX($iMI##j@W^3C__Gm1p`82Jud-&3bCg& z*ho8+l|c|$=H+y_i{yJKi*Th7sQVPqVnMUGqG0dQ_mr(!{D*l3NReB_oO%n-k;u9}Ljt;dwKN618=)vciQJq`Y;rO?;D!h$J ziu?_Pm~E`<4!p!PG#Jcxdqx1h`XOq9f!ApPw$D}8U&ZEs2uz`hHU z1LPStu)m7-w5kI@Re5GU_0-Ko0OsM65~)gJ9lYWf~UFVs*u;LPi(3MM|c(V zxUVy7xhP&2W$hiH$?NRGG-IUPgZ zs$#_)FC2TZ1BJ_`v-yi^&Wn-YSpx$u<%GTMCecvvc>%vT+)gzSU^~_pVWqp3bu1iM zdnDB^Zrn{-9ZPwHfr)c?(Lp{%(gsF6_88C^d@};gDilG7m$rqPO*WX*D}I62$H!eI zo<4cwfkr=*6%dUTw#@<+#!MwYiCLfq!VnOd0^$^xMB4)ms-+Dmrt?7E~qkqJi`&Kqx%2~ zQHkv{9W3xgg)?9}rPFNLWs3#u;xG8!y-j*s`O@sBCA;uCh`9>Ip4C9yz?zTFzA}HI z=*o2A&Z*h^^sG*xtnG{Pn#mXMoZ6@mb9QCX0#v>pzK|SpJAj~Df(*{xn8c7h1PLib zHASZWoQT-@U8mWL<$kLr=isfX7%>GM_j@dbP)J3-{x29rjz92wf0-n#zXd;_qT8u> zo@)L+L41=IOrA%~(r+qbGJoCE6<`r}3a8`o)47p2YT5foZcbHrbu_(^Wp5~+JN-~t zI@Mj`rQPKaN$qk2N)hk&a9RCci zjj#aF=!|UV)ICMRHckvx@UJ6h$oDO<^7B~5_PF6+2GrSQnlR~HNk5~4x`w|4$iU;d z8Cco$h9`Ksgh^0XFKJ8CE@1%k&vhH?e(~w#H!T5olRJRC1vLqqcPpP^rRgt6Hs;tR z=UK(MLqPmZC2#)(AWYUc4Zt~VRVHJ{R+Ix|K#BX+q@O<^N_g|zzyu$EFLtN&p0i|7 z5PdBK1V@C)rzm*de1-rs<`+f$`&=}i`|{f6k|kj7B!gEa+NKKl-_Fxh27NKq_`E%$ z{UjFHnIQp9I>0fUeZ``<6?i|PPbDc>7q?dY>^-e`$P z6rMHjL<2dn^5Hm5@nHuZ&7Yd+uxtSdpuy2!P(d4(JbdiZzdcV%UT~UwQ_M+ic*|U| zQ*OHZc&Hu>=5Hfb(S+rA-jMmiTFHM(jPAJ8t!jmIF%_W?FPdgjbmwbtAknV_7 z9TwX4ct1Y-pJG#oI83a6&&QVg|2oKd%z-?QP++K+#RI$?AUMjig3U5P8aSw{;rbbN zA|YOC$|y{Ev0>1JZ=;ehR65hCwCPQx8ia7vgA6KKz;`<|nwM#@p(0CAiy#9J02 zlRel`WT#Vy@?5L(%#v~iWcj0hDSkI&+krjQEZMedPYMtb9KRN4rehwd4w^IeWeTk3 z0oZr4Q##Oy{4xNVZxJ7Ya{MTC94x=W;iu5-UnD=fulu^eLL>ZqfKIJy3DN=o!Klcl zy!F?>$o8nGDM23;lvM)?%8iJsAd+$b8Q;Fw@LB?&V?!aAX7J~-i~c6#<&c!xK;>&& zYdtwBBne(0`P#9+)Dz=p=2d2&m}>%sjkq&3;S3_ge57ER+2$f`nuIPlnrj}EMrWHs z0?3Xdi|@BjZf zVxuzAE+iur1}0r%4HmuWS6OOZX-QdX6&4JJnYEd*@NtS6OiXa-vW9v1k5fK=c3s%h zJ<`c%b+IDI)0o;0HzU!h>zd~vV6Kzo9NHph%%%Sy*gW8||0v8Ex`9kt0DRHB@*&%F z_Y9w>0TG^ith{z^>pHI!qhwTme|cKj;ZqnVTH@7G>kODoP)pBdG`0e$4Vu`^_@&zX zmHXRyaQFdy)>Sn(WCoj=PfM4DxS^34gP|HJ8$q-w1(KVBf>i-NqiX1ofs?hUw?d0u{7uph}Bzka(nb-fHN2rWR045`wT06^nlEH1NH5-!BXxS5|B z!sKB;U&O)&L{FsxG9<(+k@VWKmc-vh*Z8erixE_jPos{W*Uvwd(c@F@(mao>?OUq; z<7I2O6N-FUrwdcow6#ycNu@hl1PE833Qp5vj{ot8oJT%*eDeLd<&m|sbshi5`Z$)* zy_*_}YT0`f0CWHV22TO2H_0CW0I`+nu*e)pFf}}7H!musqha1{#(f|OlJP>W{Qw>} zlT%#&JAOzDTK>KCIkY{^iKc_?ET4W=MxC(fZ}hPMh@#tCxa^$MJmL?(+=w$?LL!xG z0sh4AbLXRL-{HQ7(73i^xz!JKKgE=7TJ_(*!c&>CvCFQ~5pAQB<9R6)uuo{0sBwA` z%GLIIR1w6L$jYVnfCe=Zjh#a9>CrQ}y-N^%h2m;WJUy)Fi3e$216k{-`G${79q+-nFq=6|uwwZYR<>@hy=jy=R^SupQ z0Uxq?@wQ7oEeV27fd?^4E4+H`6&nv%;NU`(4b6Rh!PmY)k9Q=gyuPF;kR2iX)asQA zq&0EI6Y_tFdCN)kIAJ%~=xPfz$yvp4@SOG0R6#``k!Sp^UJJgbX^GsoaR?H0khQ35F5oj z=QvJpC{&m`)S|3)HODpNe{Nu`w^l8*yH$cmDARkN#bwB;G6bZc;LSexC0;;ONE84=m$)w?O9qaeyC!@gOOIV}l_-JbBxG|^acjU= z*BvpVY8{n-iezD6js|Z2?_eCH(?^rN_-olE^PH!v+WLOab%qTuDUgi2=1pnqnqT;C zixW*LyTO@LlRVoX>w*BMWxrf<(KCZ&mzMm4Y}DjtXq)n^kB4q{v=GjiA|Ye#hAK-z z+xl44Aq#_7fBn>|L7Lt~Y-cuw)Dpl3J)$*uSUdrI`UIec zS)|{JeHeb&W`JP)2W>LE{_3>5r^*+V73pkZAk}ciqcE-5)Gs2sGawHo^@|x6xw;Ug zJ`(^fNqzjWH;q`1+NV9SC0&DH)G8>|nb{e&p{YN7UIDBfL+v;=*Rz;#U6fKMbps3c z-_tHJ*~#8J&GygLEnH@q+NU)gMaK28Q7FwT10Mx$%*#UVZc#QdOeLOfj4mZTCbBLS zf1xUoL;Ud(&v25m9%&g7go|iy)7qeIgpM*x>_9Vxq{57%T6`Gb!u?|e$hxL z2nu#Q)0VOPccSKAZv^~ZjkOY&NLX_`?1Vdze=C_L)y47*!?JCzF&~0Qf~N2{b=gK} z3eHQaQ4rfuF8nQ9MX7-O^&H}hjqg@F^&tUfE&`&Q+S#YV{5pX3`C@03i?O!MP@z=~ zsjVtk%Xh=gE(_|ExE2@YJ@u}vS=FxHJttT3ikvG%NQzg0kf?YdRn!4y)?8i}&t>07 z>G}1l=TPi=exdB?(LyY|p%-;^yI*4*JD&49&3W4dW-C^U8v@T=Zp5TxGvaL;D(Z9!MsoZ7Om5E(45ANQO)UAPd$h(A;Bd1X7`m) z))!x2E}16)D7n{P)UoDf9=@8QF(qGyL)rdyU_*!KCw&m0IK`t;b>h-}B5WrY>e>Oh zRE&Ylf@SO`j&N+C9nbfAqte;p^l1RpyVi43JHSYK?O_`d?t)w;UK%5Oo7JS?XTmAE&c}>BTO(Ny6xHW;5 zLB=syklZf_zvRm(FgZHrDY`+y)*XRERnJaaH7}%BO_ji8DtiQJtD?Wo!tjO=ir{snM0A=yt(}MBG&n#S!LBCWKL7Y}oeN}*^BfajR!6Kq7mZtOiU6n)Lv~T^ z0P8UM<-MuNNxzA!`QEKo{;F`TssIU1YxP*(aT#GKrWgZ&>IIh*aGl2|kf|Gazzrb| zEHn^|gas;vh)|np5S-`|^D9c}i$ih(3qX6_=}7)hR_K0DbVRJ(@tsP%K zKTdM72>@SWnDlGMt`R3~G~zWJKlC!XZIsNq=RoLjf*4d9tdO*MiaPaR(@E3&YC#(< zn4a0@NuQ&0y003|pf?FuD-00093DPeXuPd#MTJ()d$ z1H{R?(P@MHHwuU-bs~2VJ5CwcBhdY6Au$!vr?qcOLPT$8%{2-?Kz!-i&H24H13<(j z&q_Auu*3IW=8UgRSg-tEa~R;J;RFb_9C=>UMSTPT{f!=|8X+Q~4F!|6Lzcvt!3~J% zdLqQ5s2Jz9}YCv#1J=>{U6sLe6~BDc;(QN)lYryG5wp*D3W3C(G-W z_dmd?cW;kVnkuicCC>g0+lcibVv>0aQl@#5WkA#5U9dY+X-K3r`3xkoC?DwjdI)g3 z;bWU(iqG~8Yf$#CHQU)m(Nb0UkjQr8+mR}R4XB%~Ralk}?ohqiY7;k}x%8*!F`Idy zfij7;koLZpOw-UfZj7QfWQyr{K&D)E;o1aE!m( zX5ouHNdOLfuvMHYlKy32#SnrBWQco!h^oMxlh1l^oi*UF>D%D*SQ@61?d1(V zLV?S)kW2%+M^~2mI+>ZPVTZHwIO)(4Odw}gS;46yBcK4v<3eia3PDPS?4Ia2;2Gs# z;{E&?z4Z2a)tk3*&-mlWsR{R2TVw2iv4Ua)_Qcw`Va`SQWbrS|3dItX9;dbvUzS%R zZ}nDmfa%|wGbwr`sMI#25jqKy&lNjIMA<^jSYivErj^28Ri9KIH=)96jP-(_WTqb@ z4P>hhY!(bI_qSu>jnA%G+3n!NX;NF72vP(w;5UO1-gf#0&Wrq-mZ$UqOIZKKB>k8g ztz4$%ZSO~9Q}DWAm? zI%LHvGoIAdL#Z4Uu$lEF9ohp1#C?BhwSZQ-&OIOy{*FmY$DkAwYQ`ZGb=X@I^&L`g z4l&nME7%fq5+KTi>YPy3S{D!SSZxM2ir#lXWvzr5BRrrCTj+xP_V;qy-8cMqVQMzNBm@+ZRoa%0n_u*#++8kZ!Kmzu??@bp z82=aeyb>*goUoZf!6L{aB0cl72Y5fM5Uoh1w}xRHD23t6Bs`BQ7@pgi(Jn zj2Wz@d}~iga)KpL{JA-l5$B95Sozmj@TDCR*Py}w{MYggSB6^Mt^Swkb z5|bb}i{(^y$pNnlVgh~i?5P_C-cPc!1Ay2T^D(A`oHA8HY;+2sy;^a!tz&wv@%gx9PRLSMM2ge&@_%`B$dDXvqsW zL!q-x7ci6KA||E!Wdu(F$sNun6TM%`51rgIDq=Lp*O>Zx7n z1Hyuu{ynx}-E}D|lY_AYOtY&pKan@@8zEP7;tc`RePwUUcASf~@ytOGoMNm2EJ!X$ z&QE;+25v=cUSClSUQ?nGqKyE$^|+2SR*Z$dT8@%EDjR&9+N`u~ycrN|n$C`LHupqP zNQEN_c{|+^rL$$f%}CPsmPMPFG-{A`FG%MSypnbg?>P0YfnewDUYkljeW;Se7gBUx zX+nPVX+g&_g3>-30YxfD%!*LetXo4|E0K;M9;v0=u|sP{Y_w|+z~LaeX8a3&`Rla` zyCn7vnN;T(Bs*!}55FUk!KtB_67Ro900Lkhi@=Rl2VH;z-ClN$!31IpIB;g z_nMS_fVk-hE*o3QK51JD|IA=$S^u)k5RMQp9IK?GxzYDjYhSph!4Tvh^(H&V83kOY-@OlpJDpE$TEG7)=!% zLzVX!u14&Wu&e+-jLflQvp1W@AXuCi(WM6Z5X-1JfOYr;v+jBC7N>^Bk6&>UeXjzg zV#%@vifTc1Xvtf0F5Yr>54!z7)vmS5$aIq(@E5p=Ak@{-K>$vIzbOu5ot?Y=pD zmu*hvJ-Z8!#%?{-*WhdU-pJt{pAP?jX`0+Wc#I@yI#qg32l|A@9}Gt!I}z^d249d? zI-P=r<9j_?cvsWddrx;+h=vplP-9v*=QtrJ&)~hT;gR^K_2;wGbDI;`ighoKThrHzaL615-(RobU~hT0znBKZ!!GhbI$(T zhjPZM9=fAJe!;xXk~S@})yt%jEex_vjlAjjKlY#x`;=tQnY?GMdtal=v?JU4eK6n( zY>Q9vn}Jm;gem_EF?pzOC6v(^$>7PB6)PycoE;ugV>O=v3<4q1@?+AP`tvYni5THN zrz9oys+^o%@T-#qR&5VPA9ydu~2M)Uq3w;YNPH$#5ObGWR_}b00zl zL;Ma=W0I4`-r6JXbW@!Fm0({LNi^3 z_i1DRD^Qf@T@mR<;cbZN)kQSwMXNO@l0V|#>o(x0$x~hCXDM3Nd*<=@U?QLdx|WZt z&g0z6mtZi@r~HE5zTGZJ@PRw=7bi`;0Wrp55wM>DmXsye!J=#mfNIQqGx+nfo|FFF zs>#X6R1bU2t%U87prxH5MnTWzHv*<}(81M0nzluM9wkp_i=5qFqGP;wzB00!=5eL2j{Cf#2U~$_%b&`3wcJFZ%QnXf!&I zTeh0aN}5LA#dTL?D02ag<8jLVa)W$XcKfeFF+C>!T;w^`S`wvofF1ZU@<+t-_l+#d z=5kv4CF^joH(>x2A7ShJBQzsY)eRwTr5&2pc$C=Y47fSAs{V>6Q~WDxsfmZhK{VAO zUww;*8H+8`o z*MX!2oItfJH0r3ghhZRFG#FO`6K@j8hc6sjoAZb=G;q(4w1q;}HyIk6PLgP*;wLoA zN|gp!(~a#hg>wY#o#hp6>N6l{U$x3ojokU)!9LdmWvqV}p_<&+S)?%xczMT%*mgjv zEsiR%OKa`|W^BqY9^J}AIqehaF3w#F5kjeWh-T76>HWN7UeL3SACj!UJXLq^54bf5 zLgq7k;yK-c2L{{7e?$AW2#5cq~o+RMAF#fN>>LTNs~kFc{RLPfy>A#s^2yUMBSuK`6a zZbm$BK||Zw*F1u@oU;84nxlnZZ{>a_=sdV=-EbxbnLjI%AT56Xa+< zOuRlBGrU-J6Fg5Lz++!v8qLsTYeHR%e3lRWAcP0 zRD58J;2mP-+_919AXYoS$=Hi_o1T~jZ29T!48fd|X5llxxLclSF|t24u}!4rF_Zvb z43%pCi=cR%R``UEthCRxS%}MeqOVIVmTD|7-*KXLQ(GFKc;s^kRTPD_FC873wc4ZF z?%D%CO6-@>x+bIan6C5o?dDIkz3!gU`4a`!Ugu{24hLCw|5#~>1QY?_d-NUPwJ+_T z221N{U0k~J^v7CpSQHHv*irohT9pxPZ(xaYRSyM~tkmBlXwP3m`PlM`pM8pf)AlM& zB?1J!m9}>h3O{s7p&@;E%lJs<3&S5m2~vS;V{6*9IN`Dlc4#(&<*)+BrO=_x&4f1I z1p?3_646~pt}1A)TvEtCi=jFa*fw%hsyl$Bn@vaZal$`6>(K8%KiU5-Kzf9CY`Oe*NK(e~#{T(Y$X zg`C?Oa*#)Inek#f?6T*s@`pRR2PwRVn_Ie#QCp1P&db5ghek|wed!DB=0S_IhGW|6 z4LXv~O-L&tWkrleAMK?iUW?eC%|okfHt8+RlR`w;*8BYHlW6;yIitT%Ph5fyL|&q% zS%3Vgp@tK~B4%b?8YnB=a7{&U58cFQS7r-vLKuA{JBD=BjPRgC1MyfU5wAco*$AS` zog;vw$zp0q54 zjCC(abirYNoSpc!>0%mg{b3{SY!kxX1~jQ`bR}Q*zVMXvJ!C`!7+Y{t*|j64@VVN4 zFwtC9apbl$d$VJ2UtcAB9%Zym-B%R4Ggqn>OXann@zdm?#pvy?9{IxdN;PQqqT$2h zeW!w;%_HbgcYkxPo~^_nbOArBVJqI@xbQ{iV`13?3mI!$Rblcg$k;oWqQF7j2VP^a z)%kTWb%`1hrt@gt!h(lFj3N`>$={YR?5I|8gy2PMnM-D$t$chR^c61pMU|Pg3{PGD z%1?Km(JlWZ_#9i{JSKs`Oh{IeL?@TRlgHCjVD^VNw$^G+Z%1y)5(54HLEU1mQhqsD zfx%_Aia4uRVxh;I$cYMI=)p62oHhSX^K%XH>izP-9q2z7p#tp8)Zx8Z zP6I%OPd)}{`H;s=?v*?g4^68@g~iA;{9@0BT}8YslDQL=OCQ(9W#`?oslHvdYou#( zuG$9MDf|oBI9ma+DxT7KA#p=Fk6cFR`y?(=4qwOAUArp!xkLZBe^9D<~Bfx!J93;-cNbW)MUOiS^9bbK* zENL6MZ~D;>?ArSd{t}0y38jQaoqz;N%hM+J+Ru&GP`3iFsu3KxjCmPSDAyML9LCerJT2bKLoZ?n@GZC{5FZJ;7&5|+fuIGe#$ae`n32B=z z^IZM+&DHxn6v)V3wCEi=sK#ZjtL042>1gKu7yEHa7J3{SUQX;yt^)zYxeC}3^$QqV zLZHDIf7H`0khyWnd12pn9r(Yvd*r1wqic7>%#)02Ckn z|K0xsp=u!-Pn+>f{|p`+Zbp>SfVn$?z9sS3K3a{ZLes>`+FBlwo6wEF!UtCf1 zD6;kB5oH)?uw#pv+LxzBBgMK&@pS$l2WuBBp8SqLZfG{FZa@ldjhs%1sg4f!ox`zD z!O2+$?5@4{hkeGF#!$TgM?2!l7hCbQ1;-J8-+~JXBH}sZ1HR`*<2iUXmFzG(FpLN| zHjDPr5wO7oBA2}P5UtZ?Uca0v@@<>6t!B>4NkV5vNln8p-TJ-%Xc6#7@kpL|R33Q2 zGdd+w8wBOTf7h7##+yliks@?av{gS9Ivy@F4a?kL&F}2dweTDV^t%m+|GptkwOtJd ziw5=*yFAVB%dUky6gs*(%%(0noQ#EfXDY~UrwhaO+t*zWZt!%UXp@(IKfT<>(DKbs z-=4x=1>-_wxrrWG>}6X@V{OWF1l^ zv67snUs{r<_0W_jKLA6EhoO3}nl2q5Yto<`b@Xn>VLS$>%pHb5CWvW5^`Cj1@0=p+ZL^%xHlipU+v62Mdg$rnBIUG4S}aV#GicZhitI#ykXD|>fc@+ z!Pr+LSVxooi-s@i>4OWt-uGXE^nH9^{*m;J2>%Bp5X3pSTC1aE$Tnjdec-+HkXg9O zk^l;kE?KNwtdG*rCDU*Mf+5`t&^-215-=jI+?Z^l9@?r}N>6 zeC`5uAA@a&r~=f0o#YbTx_ooPA@9)?1fx4e5!pH$-Z(1u*3WLr#`^N!^A;Q5Be{=z z$->){sv4@nj{>I_3hE#&qKD5p{RuqfT@^i5h0qZ*Pf;sMq0s{B*++i1cN@p@xr+Bc+4xJi@E zURDuY*#Xg(-&`JjGwGIWiq{?Kow!yvPyvDP?SK44D^wO#_lnzuPMlwZ&7^isjHm$~ ztSO@5+uVQY^?3%m8Wmr4Z0 z$~kO{rjQb{F2Hpsm>?C$=kG;CSIaoJl5D-0ERMq37kV!pcJg4iDIB8332$g|-#dUA z)1+E6seVuMg*qri;4hVe#(E_#r&xOrF%$4*n@(+l^&OX)BiDQg-)o|;?q#fLm{B`_ zeNF_IeOZ<<%IPHCn~Mu{M1*BfB>FT6>8gAcwPe}2Q5PLLF=6M@QZ8az<`mjyJWKT> zUzq2vJf!{SwHv~(923(dT>>HwTthT4n(jY|Vf*LaxstJ*F0$kaqFP7=0x+Vsp*qO8 zi`h!J%gOUMzD6a{nwB_gGmsb zjG&gfOXnfqE{{V*nc2rYl&7x`Ma7xtciYc)hU|5&judJJhtq|qfF7^;OfpvZB*A(t z>RuHjYF<*NL3A5x2|7;}2@L@eizqiL#;pB8kiGid>S5dY@{MGAoL<8smdNF=K``XK zTU{j!uE|0l+Tsm3fKp@;59`!kP1$MySx>lgc?n7tG+>gyuB9&EnATxM0xNEBOc~|Y znoP8M^SznjA=`!}}9Az42@iuv^DT&JD`KGNQ5J*1ifaNZeU&LJq=U3(MH_ zRR6aF(Lk&p+l4oqhNygK^%sQi#31YFYnR053{4KeYGD*`k+mh%9{pIehE*-pf63gjI!J8G2<%*tH_r09+tYG<_FxCSqp0 zLP6%Y>(hwt0k&J&F1i{_lft9V6`8m7luqKmNY61AVP{O(v%$7X+C~4N`|FPL_#Wyd z1>4h`+g+3{THuZx*7a>IFBUS3VqO8*lJQ4#_UNMg^$`i}tNShG4Hd=CoXR^E%PDr} zO6r5I*CY0kJwYe@0DnFL=xEkr0z?cm$;e!(-QQ zdXI7-_2Ik-1dZpoTC>Y?f{=MdqMk!j&TZYJIdnz}pWz{-m*#-wKx;n3WHOMwX9K*? zBjokKf-oX9L1u+nEQ7?^<8P(7+||9Q+pb=!W_e*vurO4mdSm0Z!Sofj)@*n1AngG) zwCz~Dk7G^zH$gp1W20@q%(*N`NDZ(R8~;dZMeKLtzFEec^)ya_nvTd4hGKLnT3i6FEUEcIyxSgd)E>YkLtoPd* z)`gC(S1iU^Z=@xCwq2Qjj=bJ*gUGfw*2K-6hiTuQHm>2+{k>S@?!dSKy&-X-x&9N+ zrDsTQ(EzvWhKBa0yllW>pz0S%-Z=XXc{u{%1&`7`Zz}{GkzP^P9DgDFKFo#*?KHdLu&3olrEpQ;lGeuGAefs?MZh{L&4~S_l zeDK&;9wVBCNY%3LNa6xu2&;E%Ze4+8pacV0qVotBBd4^>iRKR7-GNd+uADd8L3FSL zJr^wTbN!;+?m=cQnpB@g_jVJDbDeL%tL8Hgx6>64=;TP6Gm@a# zy%VTU{#$*x*yoG5B>`c_Nmi3@v#V8HuPpdDB!Pr3>CCV39t?$EL- zlTO8W2Or7Cl=uha*oaU}4L0rsWoYUfn{ zxX9I0rF!YU(e}gANc=S%^h2($2MzdrQ6oVCP`W)+$c5~jbX6j`^_a%CNYSOeQ5oHh z3Qu)d`(|v8NKwikx0ZT2C^Ci&tALqPp)~{5pFKsM^8q;eVhfg#w%K;wRiHR7)48!* zvRr~dX=8ZLPivyFR;p0>Z1F;c+>mXEFG12p65cog{UItbF(1E}!WcRriBQ}a)jRk% zm^U+@-vvJNpHCIS9-lXtyJ$kESer!21_z@K4zS*9OVoNyl#34&puik>k~I zP8)=0sfGTfs~WNpjU8~7@B~N74-&WInUm!4l7shK7VWs=(#w}iE;|Vh93ly1L4weF z$^Pf4wE$_ZnrMVCOjL6l`2Kp!V)$Tv&!S5YEpjhJ+f}r{Gr}C=lQ~95P^Q?cXf=l= zn)IdF&i-Z3FG&W?R*i7~9trjWE}#fSWqU>NuY`rMi%P)$3pc>Mf=)f2Ie>{QRF?9= z_xk72MA$*m_`2vso!Y{O5fE>!=xz$raxM;_@*@}D<};T93SSt!T#7lyMS~W*#Gb2- zw0<_?)Qw*5STEDF_S->kBk2y<7eav$g5$2ZCbVE@44i0i!|UriCl<>1Erp+1Sz{0d zQD#Z7A#p;<0uIp0=AwNFLm{dsvq?<28zDP}i6l#&fA>2U-q?W8b|ZH4=Nax(uj?sV zwX}&#v8o_p+!+)XnWH%@cnXUJwoMcVSj3>z*tUQKD=qOj?-;YqGa$+!BW{{T*mm~M zW)%S=0n$g;JLYklt!%=fSs42H7RcS1y@;4LePGk4S!d@Uhx{*;p6Qg^hpE3oPqkel zW1bViiQ4CQ1%Wtrm$Mb8$^aP4nfs#(AXss$Ja#ZpK!nP~j~VK!QzCJ6XhMq^XIr$T zzk^OxX%k^Ukm6J0zz|bbS>ryw6+^qhd=O)+0yfAd}nAu8*)Hi`nBby`m_M+RdG=9XVbyOB$ zqw(fR!gtwxtPzqqAP_IsQlysIlYW-wsTM)e^`-z) zwb@q1LHoiNo0vdM5oz&7gslm8RBWGV6w3mwYE}Yshx4(h=TTFj;8eclB)ZPR%AThm z70F3~^X&eElY&x`7wCWQ%~v}&z*+$@Xz$uPxtLlwNvtfmKnpQ4>0;)3@Qs2h56K4r zw1q(%j4G3~2r70+mDu9KmZbJ1RA2iiXFSR zN^<=a!NiNw>2m}C00RI30{{q?w5$LC0{{R60009300RI30{{R60!mOJ3Y6WUDB?t@ zP)K5Sxl**U>a9e|yD4qlpiCDCYuG`t2!xrrBXW9in7qe@R&oX(8{{84A{pj5|HAyY zQqci0jD;$XG^$v@QXOOFifppcNf5ZHZ&~LA=bc3+4LNe})p`gxv(zv8}-pM?{3BJxyJc_s-XD5uK*y>a?vY10NkqM6YtQ-UdhZ2r>WOr8C54E*Fx2~o2Bhm1LSw}Z}E zV5m~EkOFa;6)+GHK})chSdKceo@?kDeEaVFJR%e1T5jYDH()#LxPGP9e3I(J5Tqwf zI~26YV8j}c;-MCOCp{onSVWSrRP>emFr+FBlg1|jX@Jw&Lcy+6!LMw-W>|C(^X`+^ zrKJC-o7ad`GNy9{bItZ}CeFaQM2fHxe0Rx4Kq+R4RaZ=B(XiHY5tLp5RFpLWWGM3? z3Y6`kjE``kR46724P?nsH>(gu8*v6*;(}AUM-EC6Q~@SnG(5=K5eTL*AW`AcSh88F zf`m!~Nvv9tSP<|#fiq<@RAPpBfow26#`SVoLmdKPr9qvdx?y=6#aE#4z&lyzHcVph zl_R^`08_*p2ySRSP6S6Jj6*S@o4K~5_L7c{UHj= zPiC5?Ky(Osid4L&cU5zSJlFR6NZ7u;&EhniSG2CA527b*csV~E=EH(F%^hl6O7ojS z8=Y<&G1n1C000I@0js~sp8x>7>gHq?BzgEG&1O_GQLExzmJ7Iu$ES!c64yAQg>cP8 zf!_{r?rvvPY|8?;SZ6B^ssiS%9){Y59PK2KUip`EE2faRiY}kY{;Mz2+~+Py0X<8i zki#32w-(qH*_f6$4lM`X+9&C~rKpH|;cKRIM`iXfQ<_!X1%E}<&ryLQ-r9-Kl&Kq8 z0PUixgM|mb+syK1wB<*fRGMq4i?VsBZ&c7oOOQqh&Nauwc1`bKf9&E|FXf6MO(Efe zV776V!Ru{?@*EK^E;p+6g4b}O_GxBO#;=5$;|3iKxRs3iAK^q-dhx+n?o-PN=hRu) z%+zOXe@sBxr}#dHAJwSk@=mmxPR_~Kv4JR5)C}Hp)LwL4GW(X2N)He$@C)ArFmJeF ztIt=AW6!XI!{Q2S3fVM>PpRhRO5Ph-#cSyo_ssCz9=p5Z#%sJ|Acl%^u4n0P?Elq) z^A4AQoH0{I$O6G_;gb13BlcDs`mGr4BKYfGoA&F9C$}Z_1g<$q3N_0>)=s`)VhdRo z1|MnG6Fs<&Dt7t=&+c=p%UJ^m)84)dK*0YP3lI9@Ki!`a(};Afj_k9!7JMHcO=)+( zbPJvyR39J3DT?o#RT5i#wK{5eA+J6FYe_4Af(XV%+(Wo|G9vGsMJa@P!&u0VYk7Vj zpo`Z#t%)EHP)%v4g?rf3K-Lo>dE>E12d#=}v9dPC{~Hz@jg~X7EUoMnd6inacbmRp z-(#Bm$byZE4A|Jh?!fu_GSVVYnqD(mDn)YovqK=BuAyJrd+i-BQ2)AJTffT1^DWJf zo|3JWCldczVE+;F!4&rw-a3tMOLNia6E*z#8%!Puk2jEm1}&uWzh24rmIxVWw9~G> z%>@*YZK6JF{!bfGPF=4rQYS;I23&T(QK2+~VTDz8zUjXo7E)l@f_t6vTD&ZxMLU1| z_nsXY*<+u#U4ZHHNUGaueWJY?#ALq*ZoY~?(eHiXFaFkwWJG(QV2KR7(7BsudmM&X&#IL=?w3} z50`WXSZKTiQuB0;jVwq(EJ_+daN`Hr(;rDpR5AFrhKx8c)Xt-nwk5%R_RPlSoq{^+ zJkS&Sy6_iXa5iSeM@oHwv)J$HfvzuUkEwtR4I^>?q*<1vd z$--L_~C>MF4aG0f-NDhpdu`M3C^Gg7NTv8mqbXv&hPfo$g#DB^TeHJ34jDtuY@T8;tKmm zT>sBPteO{TE0;A7R1qO)6`IVcY5s0?o&B4BW)txO%|dfrSFtobwKAR@afHl_HRhP1XsgWAZl*MbX+L|$GMUz%k(~`8L&eAUcVQ0>73fV z2Z*TSL65mx)I)5E&b->I0^a2M`q~C{=dHUU_a?XPF+OD?uh1ytg=w5C0{YhJm^e3{ zw+_hd;YKAI9`GDHv$Kp^#f$rDi_NIntpG$6mw(GRYPPfy2KPxxCn;Z8mQzu)qaOk= zh~tl&DoeZNM>>iEc2||&K4qrPSeDUMSUnfv4*;Q{+H!zW4jX7(Ao#u6L{F(2NQ_m! zukACWM@w`9KD33jVTU90U&~F&wxJ)y*fuY8M>T479#fT53u?mQ73L2Fl}i50A%Tzh zwkI72>dFuy3Y5*Mkc)Alm`EUE+opkPTV}SnwoA%@MkxsHA`^!v@RGRnIj}b>Mq?=m zis=+(RlP2^g+Z)r7FwQi@0NW%i1dPsrG<3Lb_3POtEo73a##c`ZI_KqbKL>jZxR}+ zB65^xK>}xuwP9;7>L>SEN8RMR8UOj9Ao{(;V4I-9Qqii@h%>?qwcXra&XiUGTVrLyU?|Q1Ir54yz zhX6N0W7Dj8Q3Y68QjE-=kSSTT5vcU#}3itZCN|K_5rGg=Wj7}t4;68O_ z6l1aF5%pt&Yve1$=6CH9hobxJnwy>~{nR3_rGQfYbINp15gCcAu|aN3@N$W@~2or&eQ6Mle6m_ww=7Ut?L$W(8zw-SdPFX z2oRU1uTqc@gJ1z*ZUS2;p0vSGrvf z9iWa5wNiWlv{se_4*&ou5h3q7C4T?_0{|+esCmZZ+?^4Pp?*M_s1>p*nRSo#Qud&d zWaq9=7@N;=3B754C)JXCzIY& zqIF>u^OJ0sG9Xe!B_KNRl{X|{A{+G*#)TZ?n=IwP@xB##DTHCn>a@6Gu2=w4V{6Ia z27bl^77aZY57mv)v0K;>1Px8!W5E;b9*U?JRXfPMkz+C-M;H?^JTe`lPk$|bu3?i* z8qyw;lLgkC4N#tPl(`Iwq-O zG`XmdXkjZZnog7moUGDjnf~KUSWY+1Tc1D! z1O&sL;COF*V^eJd4Pee?fG7q?-vx#(5rkQVUBpUS1#+Q@ zpCr^Ac?!+)h^{MEj`=edLNoM^c(yXGmIH_=N$%0GEv_z!8VlX}(7jO6FerG#{iw>= zZmw=ZnkxmG&Wbo38Uz;f*gAMzX@qmK^Dke(l=yE9*gPorbr7C{*ble^Dzh5rY!f>~iv{tLc9Z>Ha zVmhs<42XgQ()46nNKT$prgs=_vEBU0JIJC;J=_(KFY*gnez{rOry`^p@Au zrZIi)$})G(-j6JIn6BQikaj55G37Rf(qdr_yFk)zt`v(fZk?QI0ZU48PQ+ zK+Ud0XP4m)(R-xJHAv7{Z)|vQOJNzHjm#?1czIn^t}GqWa~3JI@jJeJX|H}t9p_PX zj!RhE+)e6!Eh(a;5dNHm{&;LQA!wah-a<)z2KsZEj|HG6=0)Nubr2~y+}IELJ!3>< z+0UzRht4HSCMX8GG3&4jBEG9CuS_Q^vws26?Ql?~3@bo|C51O zO*`^?V7P5g=D{xnSK<`*_08OrgjCWEhD>LW*A4OVhk_w*;hLRYW0;yKf$B)7@^PzH zFt0&7S!p4NdhTJw9$0*kW6$>5%&nKXq|y)RRy(_#N=!uhjV(HYN!Pz;vaR!AZLBjV z-x(feN(;zLo9KzPFqk?Lmy=z0=;Kh6|2w5&B2{_@Ew#S$V6a4=I{KJ$>4_N%c@OQ!3`~cdLqew z4}f+au)M7U62*&1>CwTY%M>Ah`5a`nL+B#e$Gg2v=MYPp(Y;&)_8jS6x=Q#nuV!aI zRecZ2?c#hXh6ee|6Mn`}0*DNk$a12`AIvaOHU*#+tL0KX-{F(0h3zf#1Ki^-U#r#!;r z=@-nl@V963lI#s>i}VxLJj34DzAp0b_*^JT5#iunU93S#_{AQ)*_z+!R7bs@MwrJ* z{)l9OS9{|58W7~-G7=ANZ34*6&@|IZ`!YVp`-&XOV?y})qu@D#gXmL^c8DGM{{rCR z0&tSy$P|l}YjMe91)C zyGO?=qFmEkDPxYy0APOmNS{u2%#6=CW)T|XwiRV_wF8%->GhgJeW&M6gOfK|vdVtr z6NDDP2m$H^+(c*O#teWTz32je6ECrtCXilwa!hV{Jdhs~5ZsvQI!0Yx9BWX6DeK?6 zA|O_}aUXBUwqO{(sdaK0B zsX&~!wjook%ydw(*_kb*dqvb9YDBPFom}iwL-7YNs zG>Ryd)HH9efBU=S%Ju#_>FzW}q{+lM0T*J31*7)DLaum2`#?7uUX${+15q(R5N|Wo z8S)5^81IS)6^;tq#wWgRVvu-d>AQ5+nUNQt@djJEu*^7IMMRglY(Wzl$iGa|%=4

&C5^*Pc`fsfQtt@cs=GQ44vZJlpR>HW0Qk^}I7;?RZO+7^bqS zW^F+~1snRk1#sL_Tf3W}wHisV+>b?hIE@`e>WU*|PIAz|qjz>z38kF|vlW^WnSjJp z-Xd|PhvFQYR$da#(IU#8-Q0Fa4~!rUtWg@2N$_mY>*W4`ogYmQl+K`N3;JR7xJ|I~ z+R>*yKKw5kA94UH-~IiVkPII{AKSR2t@RTVZF4J7J)FE;_uZPJ@fhj>d2Tzk>5Q2* zlvEU(WNJbAq+)4u4fEMU)$Q!VloDg; zA;|wye{Pq3$9uf;6wRB32Cpt%^QRl1EY{_GSIFKDi{6eCv)}6ptcGwKJqc_ScVg<_ zCcAb=r)rnZ&S^~oVl80GT^usQ@PJ2qE214z~65TZL-fX_>;!;SV+-Y@fpMV?dX|^$-mo444CH-2(PTqy@2schW-CVt!xBFm{VAV2VhcC;`OUU~mFoTVJY!nlTVyZ! zZh1;8wETR<9yFI=euzT5+O`}9OihM8=8(;)+lD2#gny-Gnueg`MgE(yyQkS_(jhF# zy&K;A>@(&q!yTs1B-45gD}s;J#CzDTplT-7`{^TB?+gIDulwB=?4vp%{?zw>VXIZQ7fEJy&(D-J*g;xsl%kJmtFv`5NDvUx zwY_Hy(u%^PR~AXA_TWsoM`8~<=R=UOA{?IjQP1MP?d zi%!a|$n_H3d0CU2&d<4Cl|y+TR?dq%0L7&yS8`LsBkuVHbZax6365oz!5KJ5I~BxL ztl)A76QrLF0-ux7(|Qu3L`jmXxOh1+ zZMx6B%4h5wwe||8>r6k$G@>u_`}d@hL6_{zT2j`yOK+7Q5HKaZnFUak(0?2gP4NW2 z@y~rHw59V~mX@xwP9>0T8x#G~Axy5;h+M>3uWn7u!aHpci{#OsPR?X!0*d<`YgFQ& z4}$-MvnI*KLXgJDK{n3Wgyih=k(BuGR^g(h36r)XhhJm~&lp-Hch zWL%QYc4Kh&0N~Qdv@hE&;M}j%sD07D5CzxaP^wWUVX4llkzH_;Mt%%OBvfvPk6Zda zR^uPiu4*(D;;(HEt8RV-lZyIm#O%WIv6VhtqAlLQ^=hM$g)0uG3HF*N zwSiXFKyG?bGj*cl+nGG@i3p}2Ac(g@n{LiWsNAQLpy$cxo(2l@q)!Cp?Ns%F7&CVm zf;3A=B4uBOzlYJAIS7y2v8^yge+O0w;v1};paLz|%G?{>m~x-J@F{G;|1J~46z5Uv zPY1VGw8ikTHu{^Mf|mWUzX25k z*8mDF&80mc;Dc(UE_FH0;;x?b*16|o&mSTQ=@Qnc7GD3U zGuB_NKQOt{fOlBHvyyul7xj_Xr|-*WvNAY74zdcg_&f{&CtNegrZPj*N-2rsX&32& zfB@~Ez4a*rk%wNErWH#!R?hHCDsk)7`&(2I6Xp%+b4*W<<~zo?F2VPHdsdW+*v^6)wy zi3nIM#|ChyiA=@Uiv5gMqG$3RDN|FEC6krf)^Di`(HXIZ^Q!K=AP<3 z`F*#(Q|rs4sa}N%<=~zv4h~hxpPnUs&`G15SJpHG**pP1B?wF(8chtbs@TLuZ8@Ue zezNRL@b{j)7+aK;Pzgks!L^ReprW&t^X1=(@qB)7`jz9!9pM0_GT1>=0Ehp}qaZa& zXv}VZBq`-M+RYFzBN>Q)C74pSzJYHfvOUdC7Ijl1+upj*M9B!~o^geH8JV;>9lO(e zB17aH9o#Pr5??dGG1lge3+|S%2zdzNxy4vkMwA)I+e$8OIeKDjxES}s>P&&4?~@Ay zK-6}1muVb_{~(8l9s_%IaW)MR3_2LBPeL+2PN;TBq3Kr7U$*(98Pa!}tz!~P8A z5n3RViSx%pO)S?aiUtcqiK}qhX6yy5ox>+;>H^KGZvNCHver+kG%vt_85Nt}bd8W| zaMip_#I241_81Ok=)e73qHzCj=TT0fILy}app{T$*vCD3S3iZo^cPMsEObP+ka*Is zqeshB;#(V{JN0wbK&_xDMJQH?njn#1Z@ibk$mb_s%0HiUusFqRNxpmFSPOKL7K0;3c2-tA|` z0Xt68g!soCpkt6f8}HITHVUoi?kJxA9*y8*N92VwnEvX~VwQ%$)z~-H;2j0`OuB;d z{AX0L-fJ@Ca>}wWLBazIm{=k7ssZZAOsv03$i`2W3z-q@9R zxEzHt&$hsAurRoy4!q7%mPwn2m8AUxBlIDp-nr5@qeo89!CvjCU}b-28#1%^8TjQ< zjQe@*^P4pcn`LlU_Jg?uD&xBu2r8IhJzfwb!)Cv7teHm+!9TPB$H*%M2}DbNZUygi zM*!hYUEtn98&dUyY`*ehab$ww@sm$TNR{E#-+-lvdWJPwDkv2NT5N1b z71Tk!cWA#^3OJ1guAgl?yyZu#OUVIM4Yva~K`iYS%$YaQ#>@%Cfo#1(kaLk{=UE?l z4?5G2)}tT@?xvFRIAlxz@F%D<$jCVP-wEhqf5**~+~06qBblsrACdCNE{SE2Oax#g z0nv5pn4vwyaEt>V-{uM73=I~1WTj|riE>El>PogtE&xik(Wv6aYWXmi-m z=U)AGa9jBpzdr*nRLgTj6lOYkp0}(N6wRrLgIxT4w(i9hjoOzuvXb9RJpPE{YiIl3 zXIEq{s%K9uln70NjwH_wzrew#s-CB=*pxs61=47K02-sK0F_7kJc-w%I~upJ%e5j$ zPuD;9pvJ6wOR8*_s8UaVO`+u*e%}I@889qWZn|D%Qtx0Jx^G}4TV0^M7OImXtdh0p zaQ!Ev=rcTc$dk=sc43WUy!`vMUIlsEH>1}4YI@Q}jAwy~8Q0!ydPU3q{s}^;PNU~z zs{g4T^1&=oHRoXq6=AB!E5rnfHsWk9_OFb|t|xCb zHC{l_xt%;bnPUJ@uT~AdqrdjHK=!<{PT3FZ5+vF52q=v z8Lq$dT44kCO`BkZoUI+BQJ6+1b%<^E0Rr>tyXXOcz0zi~c#JauNkSMC)q4*!t|G=2 zV9h#NS29&$H^sPPV>T=P1E>fy$^OV~XmIh{uMW2T-GLmx=~qsj7H^I6bxDSD3-Mjq zL;yvY4oXUuE_Qr@>U52Tk16EH28tCZn5%*^$^o$vtB$7&j-N7*q_)O4w z18fPA*33dF9)Z~zt}Pw=fB_=$r&v}taq)R7lr&p;CbK09$0Q-GX4>Iml0Z{e4?jT# zRkxwOyoD+vDS1y)R?%SrgHXqcqv|3%;!7^mZ2LcSh*N_3BN+Sh@8}L)LtoLvmv~xa%!g_U5RQFwym;u1HaHspoM$d%mMIJPD?I#-((m+H|6$Q< zicbxjcftOi|0MckAU|4>;(8CW?wnDO5@6_B@(|ni1Bg2VuieU!=@85(+{DiaMPKMO zBk~Eso=?yao)TX{?_PJlb{??6Z)esgG)19N-c{UZ;WuCes&EiUZIeF=^XW4+jv~yi zD?g$(+-Zg|(uQ#7PbY_uO->VfZer?`+$)bTW3LNGUl>?_bSWv3{am|u+X4py0+Y)6gmoFHF>LXU1B*81WiRVO2@=i!4X4;J)8?PRInL)|_=E(Vl3DepTLdAPtyj{wOoF8D0f)jLt3SOx0ht^67l4(x<9KTLjbIeo^St3&1l zE0qKOJLPS^8U}McHb)T|zt&B_P|X5YY745#w1X{Xrl({jJwFn zvtL~9m@i7(*e3Dl+obzUiwt@s?{NQ;DOpUg z1vHjYeJ_}=c1x9aqLt(;sGTp#vDVrSO` zKpEXSt0<3=++2QLGKL)r8Y~d|mjL=O*f^_qA70?q2g3VG>Nog?I<4X@Oq=)5pJTuk zd`t=Ss z#Qih-&;1IxJ25C`ceLpGW522-@C7`>R_g!>%!OiHA?q4Bnz>8Y%1cDx`pV1ctE&Bp z{>B>Wk-_87ndEOzvo7N3N`c3LSKQLByTHyNCTP}<%GrOg<8n=%Nl1ipAkaaTXg)!Z z$+!R};iIrKWc32~_Z8>%7m@!vfsyQ-(PV z-ZUxSukqDb#dEli{H0ioMzj7;`{=rZ8qPV^hl%MSO^7~ZU>PN1PRIA4)I)3=QC#8#;vOggQ2eg zpqh~xxCwsyhMx*mo)LrKv*_zjzg>_sYX7Obp=*PN4!!5>v@09sZLf-(>Q`)5jAZZq z0t}pX0Rk^0Oc5ICu5cCR0Qs2s+pwkEKIYg6pdez(*sEFP5#ZKvsEouW3JU~f2lqy) zcIibj+N?`=56Rjjf1+A02G&k)<0B z<+oTOZ*q<5O=VVzJizwNbg1AWgA~oE|3gGHP#=Qm!@HbS9~NhpC)E*^N!T@oMfI7{ zJc?;j_>5x)^c>M99?1alQHH$e<5>`H#0pP+NI=8*AYNA7-cN(Xzm}JuVSlM@uJsv7 z_}%L^!GCchE5-upULYK_$h%0sc~6ApUcruEe4A*8D*?M6_A~D zt#gukUN0@jXtES9)-QpguV`DQUO_7r%ta{IF_kD;Kj{bWD@WEXcohtfiF-$#{r1PM zTs0w6*Y^&p5&EZh$Pq>jq6*9A))D6)tHE0qWKWf)^2cV@IFLNic2mDT%7o2aNt;vo z^ZPLe2uU~sX`0+1?uQj(6uV&~e=pDs|Ks)K`KRmj<9&rsPTN5sC2Z#BQDVkCSK@k& z4;ZIcWQOe*d?pZQdRBaWmq^;KN;-n|#Bn#NSp11CW@M_;JM!CK-4jz|7vXdj&5S77 zB+2(YyiQHtu4@+AA1npA5kJyxla|1&vRL0Df&4H&ta1Qf!9ozuIFrk>na}2a$bBM6 z<|uikLjq9gH!&gOM2BuIogZFm8@ng?m4xWSdK9E>+y`RTF^18%iciX<@-%TIhV6g*^ z4=Y~hsgT%m%sB903{|0Ed6o=!LhSJ z@197=0O!xc0%ld0-NWtPYJz%iSkIPF3Tn>!k_w@AykBC7IwrWw+GlDeoI(IM6woQY zew?GUQW0@Hq~jt^u~S)_6+l6NV*v7-EG$H(R6}AO=&L?JeqJ zDg~aqK1sCoveB5z)1iYB)az?p{OXCos6>s4xIbwS%RnMvZ%t@k_G)dB65Bjvu;=%l zBR$aNz>TetrlS2d4Ng;t1h-#5&iy|K$0JzvQmNueab1XVuZN{X<-mE7`$wYT_B(e* z5C(x7VHqo&4j4y$B;lb%FrCT)k?T_VVsm@g>&scBj;AqU;^zN8%x{qyVZE)1Ep?Lt z@&huwT~Hp4PxJW;Kkd7t}j-^JrG|Yk3$MUo4xZ+7lwSPRJ;X3^YH-6#nZ0&iF~j09#75 zbRF$xo(yX&=R#aVWNy{lfuY4LMn)N(+ATGe>;|_yeJ zExCzVIQ0Dm#qlOo6wQ27ko?GJ*J>}zAdI3wyS=0|7DQo!m@-kF;H>ixCF0+#>?0m! zJYe7-N@~;XWAjlm(w}%R6zM#}_w!nX&4m<;H83Zl?zHp0gYC4FnMZ8pHrLKeBHwZz z=6uVSn1sYi{r8oRyFyeUxWjV|h_lov*2kl!3`Fzs`PHgG${A0nz_s1B06k=c06;wj zK#cWV&)`9vzkQYv&NzJXbZY4Gn=G|TN;7+{mQIfWxdNKqsK;a!&e>L!LX(77Ko}YU zEBBC8-ITA(tzve5hOUmIPzD5qnwTa@KQtgk!xYhnVEXt3au>DDl0n+@6*KDK000ZX z0N3Js$3Or80{{R60009300RI30{{R8G>{<*l+BJ1l5n9^C?*mK5Ux>$U6vF|-S9UH zsu>E248}fWIVLZkFB`qyb^HUb()4ep0*8R1>y;1> zYCBL4NCu$2sD?J*CQ zHlOUTT2*Pb^S$(nX(9+Mmzgm@zHP^$zcqC{3;U~j-H&ag-;ry0;_@L1l+~ds;X<%b zOcWU#imJ^q#ex|bzATkySYXZ}kJZ*VJ6PQs@|Gw2E(q+}) z17lTVur!kd^Dec3XG_Spn7XGqmHt+mlXTk$Tru8el3abfb9mwCg#~5cSY{7Q;^}$6 z6L&|@#%4kRT8B5D$_!{5_SX+>v6ZT|s~2Ng2+0Pck%gNErM(4^)wIvqH*1Ns1H~pG zd?#R;pdMF5^bE)Y%E^M=B@QXVV9o569S zw6yuKVIjOZGv+>%pT-PT-wOAV97}?3rb36(3WRehZdo?Wfy>S-L&h=aU4cxy2;&W* z7!c?H00om_YZQx2sp2dMEO1*uE8()Fr zCs;nN+PH5IczT#w#h;xfolsrj*VMyhZrTmoX9&Y^9;z0e!E6uvumKNuE$o?Q)NxXKA<=?nb`>#NqUK+gev^cm5`Iri8eF!XafA9OGkq#hK~E0 zTm|8y%&1)?W!>BvuYT73Z)U@uG{x0?)B-xrf00ECl{|!d15O9Po#GHH(ZnoGLo+vjXJ$kYDidcXnUu^Jyy15(AhYS2rE zxt62OF%@(*@(tSG#WoO`HB0Ohvm#$Gn-+#04#L%RO)r#nAVMvlzs>(B*nnsU{O7T( zv-GPkZwoNe@{OLT`y=n+@%(7FO?tO2ONLE7a%58!{^zFV41(;uG9bq~LaEocYgZYA zZ+2Z}&cY^sB~Z`540z_?WSIvXmcopIy1Pvl$3(W3D-56pcj{Fg6XvFp-)D<*Gs$n> za>8l$vWyF-Z}MQ~L(vMG?r#_O?o!N0u-hh?@mi9Ed2pnmLu|WA8W4kDU%@thW##!vpd5Z+t*MloFRn*`qxPvC<&eB2I?d{zC#)gTWV0I6`-It@v!q zF(J(4n|v?Ah>d|KtxtX<2e>T!gc1N5lT!y^x{I}^Fib5a=CnV*FTuB;go2+cv?BFs z&j}C;CMr?jJo!H!HzEdToi(dvR#-`(Ov_JeXFw~C0%Qw(__D`7J>i@70`sVG%=mJP zdij#HqQmrO=_&MFaTBothD$R9QK?zKynzg_lgJBvQ{E575BsgJgTH|ssfNf&<1UT#XAnH%!-4)N3DwLp|bP%xTuHz3tki} zoCbtYq*r~8LT|_H+EK#eSMc<8b1U6SvXZQ&p5iD^W?ob4JL%WpO1p`E( zdPJp*fyx}UcR;g2^>JejFc&Mn^AlytrxHAozg~eO8K-yY<{C2I+{G)17?EoVpp8KR zwBa04yWW`HnT3br0EG!S+|v$Hl4)sqnVD1s?< zHP`dgl=}^z?r>nZ3;Z35pIj{UXYFhgg=U5HJAE*0C+JGvp64TftY$#1q=L;r!&9Pb z0{hbUjCMTd1gMk{;xKEO@vqU?XUQ5SgPpEK%@^J zCg+K~IplbHh3C#{fi&3xoUGne2q5N7ATFF^ya~lc>H4#tH61zqbI6=>=ZYhf9K2V% z5_&)(3Y7h&j7dVcQHa&jrYTEUrm#Ee!k1dXU*zc5Wetn` zZz)_e1*0rf=7<`ehB0LPZ>|)^6A~B!ok!~XhZQ2us4|1t3NOCmURyBpZnmX^4pXmW zk+`!gXzk3D! z#8#;Y<|Il2D#t(*#V)^bm{e6!SMhY;Gx)QrF<08WAGEXI_Izr8Srt0QY zf_svU-4-uxYsRU)8(aSW(3)W?8l-9;99f!x*G~uzJ|? z0;1(?Q5~)z&_F_f>BmSB>ljqOLpIdY7;)yiR;3*?J;%wL2(<|SWO^%7$L^Z>FFEME+h zNq<>%jY<3}lQ>V}I;bBk(&pfB!FBBYLw-W6^^%DUzvX;V#>5vprA7>ZGuma2I}et! zlm>;K1SOsxsBI^7aF4n-{Qf6iNo^C+;AQ#&rzSwW3f#k(c2X)M(H0;tM6lkrXMyf= zq?Y#159e*+~o{V|G4iYo9<8vL5Y@*V4jskR$1r9T3IF3 z1Nf@;oC&DExy8qrT$z}|O~s5z{o-DW0*XDm-*FlJeatyhCg-lKKNM(aQ_Tl2q5?pH z9g(R07PO1R+J{jiUMs?X=4yG_@!clyU z$9~;dy0CzT^m9$$`{%7(#lGlx8a5h&7p!gD-ksSOn zQ#J)-YO29%J|kS6&Brs^Z6{j!q5?ITAtlI4ch-7Of%= z=EbV2%@aC{@?iv*E`&0z7MKfDI!})WG?K+t3mlc`iCHuh5 zABsT6d^pC5-=e&I_d=PL8CnbHeLmli2Vc>VkYyB~cX<&F0^RxV{7y6A`DnJyq6>Zf zrT{|m$QWu~Jn#?Evs7W zk8>i}Xm|adH%Z{(=a3e*^NJ|~e?G$VGJHi8@~i+TG_T|{C-dE4&j>~S5}oD8Y60%p z-8sJ+2d&%GQ`;6VW}#9T?O-P)c4Ox>MmzciO>Tj6l2Sqx?`qpK*Y^)zGX~ctX4~Fw2${Okw^p~ zSs*eW5_&d{7jABF0IGCEq)r7y9`iLz8=n*>?Ob%rf;IDMqqkhvctt1`kA6^Dc3&fW zq*?O-EM-2c|0o!(T_ZRUuqdQrr*@f;1oyp{RHche0C=-oLTrtCZZpDY(yd4z`O?50 zMuGVZPm%*rl^N?K_}z4LroedPAHZm#&8*nGzJ%Td5n2Mdo5pV)FLD<)o66KQPiP+S zx70^QHFzY|4K!jHVG9GFX?9|FBXJh?GFBxvhx#`V7Csmrd+)mL{Hx-Lb-m%%E0vv4 z2Wb}Eb!)~K+@nfTg=e{Fk&Oxe=_R<6#F^v**GvlaFJ+;qd_1m@$ESdGVAIv;JWdm=y`z3f(Fea*1J?KjDU3^3Y6`wh)F`o zNU9VXjMCX^tN~z9SU|x$w;s))B`L-woa7Z$Zs#dVuqN7~tE>W)AWor-+bW4kAL>jZCG?_5fS zO)6p!TY*1}Kr2KAd<5{8gm4VMJ6+bN?eI%>FPH7qt+CBAe4RzrAt$B!Af zYh#cFAfn2HG-e<$lYv(_JtGw-jli5qLtK>HwW1wC6(0r17iL9u=#OrgN;0o#NXQbvdOYqU3aTV)Gt@NiQB2OLZ{J%QSHDeV0 z#CucrdfzEgDDXxL(HJ8Q6MtSd$vdTV7gfQ&xhc-Fok6FKW$A~qoRN4I zOrf|A2PZvv{n)Uqk_0*g^UMPbS1^xjkL4{`fktM{?$z|s`;q*85i_+G%hwCc?}tC_ zCN?S}*$91D_@}ODNTpFtWRqNK}0ApYdKV2{k6vLqJfLE zJ@F`k4_IpMQUz*T*{w3u@zl84gHTM@+`7}dgqS>}Kf;po%L7kYSv1w1G^(2@{~9-=Vj87jhPc2=FF45i)$c8;V3r zVG+j~YBNyCFsN?Cfm!a@Zw~>a#TV=`g8!Jmv+VPH&5is@Qe%J*vk#4e7-5+bt)(v% zf`85(c8dxwnEyDQT%SpA!1H!}2);II;{3jQE78Lk#kJ26hFuE8o$x(tKeK3rjz~2T z!Y&$_r>JRXN{60Z!G1iY+Nb{HrEMl0k6A*xTRH$Qysp$v?^K!;XfYljWG&4=K2cuh z0L*7dtFjVHkb%HCOv?>;Mao5Ah5$QgNGim^pU)*x5}0b~5Z0-S4qr4jj}=q^oM8FajO~W>47UPe*1a1? zF(a?1ry0)V0v!d5Sysc=tTDH}=KrF`Cp}1K&0$!+Fg)nD4}wkz7XQ#@S+jIYHDp2m z=lq7|lQ5jTsoA?#Y`MD4WIia`Ai4@~*u{#1tewJxDRgd@4{ZjyDr+esVEzmLmaup90YcA7y1m@lOH6|9O4wljI2u zAk|XrF*rt1zkVzZ1cIFDsKUHYB)xj9!iotV;$Nb&`*{dTDSc?>q^Ew5o2le>jk~AU z$LFs_l$&+0QkOV7m@PLkg3e2DwCF&2fbr527F6M^w)tSdeLv*0OEg&ks z-6RsLYv9i(6&KMwa3q>MT4Jc<Dry_6G#+oKezNpeYz8@I0kdGv=UX^ zinzhY6%XM+<(CuE`)4LJ&aNB6E2%1)b3S^tgj0ypQcm*Jrj4|D)3gU3e&0ud@xXAC zK3fPD)<^pK^!9gK+fj>AI?tC9@eZ@x6}&KpP>W`qF=UU;l&op8YH&)W)YzSEYI3$G z(7v_L8JR`TXqrw(kSxXktW%Z<&Jh>lhd>aKOf056q~4eE#NGScOCynh;JBZ=bl+Bq zAd735G=78}NOf1}lIr9m&(#i+hWi*+>MUvRY>IoBpokaq|<6T7 zpM_r@YE`*27+S|fmi8e2yJxw_v^yt{!IOFIF31qgBgg~etOoXfuE+@hM625tPjwB? zt^0cv6;pN?B6Vx~QEl=!7eBEGOA7D;{qF{T+Pd>z-eUKH$#W8Mtf=<~%0-E%E zzxS0T3tE{POc9FUJTi2eVYR4Oy#*P305O@!-y0VtLtcH?0tot`{Y+qnL>vZJzE&^@ zc#S~t);<1*3}rOs!1njqh*{4g>v_fmh0yO4PFvHk0$3Z0xn8o6p-L?V6~g<24UXLL zUI=20J%QX)Bv01Qw#p2@$?U351l&og_3`l?cJ$w59j$#gE+0|Bs>5=QYXHQH-X2tP zXC=}}B_s1%y!)eNRX&n8O}tJNGG4wPQ{0!u0hgbK?JgK@0@`DJb6M&NEL@WTUn>~^ z1^(B@qsmeBjCjSr9G789zH>>#5yXiNR82WEu=6DPxo8hf`7qJHJFLy{Yn=FLJL_!)kaH%`Il}Jc`^U`DaAhQefXxl6pPf;VW8g%gD(t)pAEC* z79@2|N*}N_@W7EE&vPN-XPD74bB*HzWAp~{FnN-@U~QXR>2fLZcL|KULPI9E(4o%Y zq<&=~AN>31KhJGXg1j7orQj)lvJWqDYT$O1RoYB57_`o;t=})bTyJnqO)wr><@j&@ z8Alv5#!*x$J&lI#AW+d|3T8tJsif81|EvK2EymhVR)N%;5}Ab=rwQQh*tR@~M5!R&`(<9!m{0W{+k8f}(-NyccEeiE}P^G+Ferkn1Y$BKVsz8gUHL$$TZZqz0^}K0op-x>+VMtdhX2D=CZ;JbM1>n>}mq z2PJ_YfHtl4k51Cx?)85xR(leg4hH?DIceMlKGVi`%QxqAtJg<4=S?c!h^C$@(SD@? zVIy~mTHD#d|2FoJmrO4az;)|iZiH?5@NU^YiQG6#E$|i1N%3xR$V$F}Y@V&-p;Vb> zRmDsJRzbMKB!2~TBStc`$FZ;E7%nVVxcgY>?ZE zO(d?x7%$&_l}&}f14hpt8EyQ`-r!A7P~Z7>(;hK%Mul2D-dSHkf8Hog=>II%9hnE5Rc~+TjYv!1G1N*qv?X8@^9Q zd&S4vjNf%eCD7c-rhO6F1S_s_bObo?d@UTP&Jr6>R^2TXEi%>;k_q>f5$ zUCU$g!)hE(Ih}K$X5nQM9hHzp9c>GhMJbAfPYO6XQVmp>wy7B1+}%B9c5RD6C9kVs zbu>5!E2nolh2c?FS)5=DePm#OUiO14O8pV=#N&#}KVkwcBodW3HT6BHw*$MBWS^wr zOJQ895EP9_R#w7y=f4UTbjlN3>cD3JXc#g@z%eFA4b90U;B;0NpR@YrvKo0Vy8w29 zn7+L;DjWW|A-l6D$H1R(tGi3ni^k+3u%h~YKqpW8chK;qbtD~9=_C&BplA?4%7|zB zis=FNmJvRLz!xd3nD!vBOv1bJs-%TH-&xs%xmRS<6=*1G<1G^|B~rnM&3o_`Avu?R z0W|{M3{dxPDmnZJ#*&~gp|-lKr*PV0nZ7Hv*e`BfKx$R?H`X`r2$tCnZ-C7~=@G!d zGEEa2ibh#ca0VVl2Gmt;5 zL(E&t^8lGG%lomGfpp$4Rhc-^Lrgqr=oA%JlWF1~|68kBjWzez(&%M5QMlwE(e`^v z8Q9AWt$Ry*7!yo)^?@^ZP_u3 zKeJ}T+Mo^7K^wr2beEDa9oyi`uX`+pk?IE}km6YP~Q=ml2#!%2N0Y+(sJwq^XQrj7ELQWO`rU_RanZ- z64)W{`pOEdTe;|2Y*=VF911{q1D`x9k)Uz3dy(22%3p{VY2V5SrybEn`A01|X_skE z6l$uOG;v*P-}wsiI>la!tT6tl8M5|doze9Xub`kGjj|nsVzo(j#}5{`vAM5F6GKYh9m9k632;%sOTO?Zv7Sf z6{go~H+iOX>8F{?umK4dIqMZ>+cECyB6gD1W7pIk6`U7@Li+#-ckDNb-&awOT~_bv z0W>lj1?u_-4bv?E9u40ad>^?MhmQ}$Z3a-iW=Zuaa7VDnQf5Ltj{I#WhxCGw?eVZN zzXnfmN_6_(9}?WK^JWD2 ziH)oQp@`GWB`(VJ=QP-ArOkdqu$`J%Wy4FR?FB?`4Cyg|MTc8*-YX|bRI^btG5hUz z2W<{FYecM!S0dCvM1mTjCtZ9^=K7A8Pm=!K+8+7BB}*|B9K67IydO`4MY8(I@{5bj0I zHQ9a#s7lPPTsxM^kS2o(wtuhSq)Ahf6b@6i28r=<&m+U6pBIN;b!x6pojo^M*vwX@ z&)F<@rt5z#>LU~HNQCHaz|lkbrwiDAe9~6hF4=om~vua5wC1Xa{% z)EhLbFKMIBM>fhlQ*A#VA)Cs10ei^=t9N!Z$G~$l9nSNXs@tI=qY7Cf5|F}M!QSrn zktrQm0+Xym3{^5+-BR)TTr2zc<=Hwkz`9*n#01^{y$~nnGjP8yNzG!e9n%6af3;Vg zQv9D3Hin9q4H6fO0qWCop42h?EZfIJWmjV{d>Vg@*<)e~^nQoTR?ik!jE8eVqj~YI z^!J4*S+XH3o{b6d_Jo+I$DMdeu(k38jVGh>7Xh-SfXyXnX@}cVzc^XI+GjO0EOIUi z>*2%c?EMMAP8R+^@LItAZ!Nhpp*(}I&oWuUz{bOl5Ks3O@TcC7*hsi0faZ3%dx>2i zgj>5Boyr~JLrc2o<+b@_sn;!aKk^p$%WWsm4*G}HsFL@#T?*<9rgf3aU18);=NTHJYzsz0JDofXe#1%&qS)@ zu#8ibWR_YTxI={$9%&QR*7f@3uU=eDljuX zuzTMNN?*o_T{?(eCfD!~ZT^)h*F>M;B19BF>j>Vmx>%WB+=1UHzC4HEu@fq9D7ExQ z_Kz&%Y|G|J#M8WOjvnV|3h(ezq`k-k@w5m;8 z;{cTnt2HC&CfM6<{8e3QxFaRdn{Ab5qCj=nXm1J7+bllLuFB#t!Qv8*pXIcOmq*Ie z-55A|$rMaipKT(4`)y%F$sJJS7;#gr&b-EqVq~z868A**im7Xwslz}p#Qr++QrD*r zzDz&5-^yGcina8H=2S#JnJo0mDV;~-xu^jF6atZWwz=|eMkWH2l&~&_1O~Q+@!Jk3 z2kKJ2P}a86ldHtXQYS+gN8^C%=;i)Dz_fFY?nzVsR&DZOz4*04&9g`9=Y}J?kc2xN zBwQ=`Zx{wY4$x8mr%1S^i<>>}N9i5 z+*u}bgVnTUS?IY~SlD*zA6)&>VW{U$2;zv`8U%$jLtWaJcOmG^u)zlGGQuu6GMa8H zZ>lLXQcZbJE;D8U$G_&`IXOsD7)e(qn(PiT^e7<|yodKj^cQB1Z|~+2O8v;Cq5c`; zMCV=SMPMu9uv)r!^Ay&^`GHH?eGe_P$d3XJ>S8RCL(RI_Q_ z!aAFg^WMu8W#LM=?AOE-^kIF(xHgv5;C~e84?_^;n)$H#{F4D-ufrjb3nM~|_kK>m zo!}ey1HI{yT;kW}#)4pToFqy{kov1ihJM)JcMSxwL@*E0zw&RV7ju_ml#lVSEeCU; z6OZ0^KSnm2g*BIOM581M-ZxmPUKWU=fONcxqhZvceMVm1<<(B3%QF+qFi^5ts2q}4aO*mU-VSo%qmI( zH&U+tX%{duJ#ND`+?VEBn_*}OSl4bJ zgz#bl4}XEk2E1f0W~5{$#EZoJ!T}>UEEBy{M@}1iyebvQT9kFs7c{mjpYhYKiSOYR zK_CK_3yyoakGvqKb5Y@`VeNm>m= zeVO9JsFeBmZR8-(Ln}`5`jqPesy!ugIR8$)Eh4`jTi+x&!^W?Z-5I7{$Qm)FbK_Xj z-o-Q3O2RH!8Wm<3@eihnZY;Q65xr^DU6r<=>wPeCja6|B?(|cL+8rkK(XTl5jLB3oL>8eWb*w!GGHDt`k$sH=%q8kGm{~p z24z6WNj%IQvbq~%_Tt8#r2~z>mE}n&JRveY(K-<+kIDhV}N&#cgP*i@T`PoOjATRLT4G zDFuo(xda|Fi~keD&tB;KXBMUkh?P2Zwe?I(&hGF}bp=ESkTm*`=g~3P>8P8TH$ghH zTlVQHIIirsIC&tROJ!{hY7d~_`#HL&J%-x?PsPWQG;gN?mT0JGb=yQ~p{Tg--$$vG zNw0DKG18#O=wZ?4ULNx7p3c}W#!hw{B?1woLti9(8JDpq+(f`}gt^|h3-8vR;lf#? zFxQ^5R!T}PH6-2u^c5XK=I91$Ikme+Gb01q=WD>eiEOAtX-a*3?kH{4STecoD#B*Ckb?12dZPm%a^@5U)G*QNW) zaS*~oA*GOm%tNjyR&?IKX0?yL z$8Bxe+d#CEQNxhMmK+%(QB;Y=86Zu1pVECsEg-Md)Srbyy%lJUUZ7?@Cu(*tJcPJ& z&%@{`-V=QSP%`a5zbSJ5n8oSnS#tZbSQpMgglYVg6Enu~iG(g4%#`XE^uKH~!)<&i zJp@nqWbx`7(^fs7+INfw8ch#9vLNu<8PC+Ltl{?)gz3aB&rBrNUdRMqkX%^Sw{(%$A1N}my)AIYHf5DL93 zcmxU2YOs?|Grw9b;H6K)F@=$cY4dn}Ai(u9F`#8hc*j@Rn>sV zTnzKZi<>Hl;D1SxrE?Q=q}DlAq4K^Y)a5ez6m)z--Wx<^H?Mr8<4I3N$>8_vWwQ79 z_z2f9vH6#iHWek#{x%2zI2Y+A*4Ayv{nv(v5{A{+&b3!s`Q@cLl1bvTA~H z!PE05)ktL!{4>`ye7(fBom!2Y2{0m~nlG1@QRgB#h z+es0hfATMI#{eBC8!w)&uNJa%a@%nN_VojCm908_GSWI+Q?eeNZ5rPIhW!!#+-qVg zY(5&;i&kA+c{G*_8)(bV%)oU1{ta^cB1!%!W386*+otP)DxWe|&Ak)kn;xULLL8O; zLz1(-N2_@1ADU9R$1}e*{U6l9jDa1SZ)&mPR@!zL& zBZLr`qiI{9KDSXoa+=I|(`0^9r)U;H8gV&o15Y~uJja+Y6^J?dfQ{guP3F1Ty5I6g z`_qc?DADZ4GusO^BAX};28-=MW?+|T^F{E{7xV-2rz3-zX zAUxj5u$)1Kjt-X5Jj3(i2_~pB0$mL5m6nW6s}`~=JT-cxZWgtvMa)0mk1)vT4r)dL z%4Y&ykuQm3!cLNBI)km?z8A_w!Ql)7fGf}2zfH|yg7!lsUel<~3bRNVUtJa zHE&%wIdkD@PWtk>k`*_k^|6w(q;G)b>E5KQD*C!Bfv(rQw@L$$Uq$|^|8X0Y8ggLE z(L^2vt$1{%a>2TU?7@5RJRV#;N zktZi(Qxo@pmK$A4AJe{FK|e-co)h{ldL(AXTm^C5iGZC*(8P~(x=ZLjh1gq8_EsE` zR6~@p*Z{5bC02I#Fy9Av$M-TaE6S-3o{92TERDlqHH+Nw-~zw+O}Gfce3nK<2h*?s z9dTJ5-zuN%T9_cCI_0nfbvt{10-* z%;Q6)q=Ob>tPL4$llbhD&2Q#qI^7X;&|)u8co$mTfGrM{eMvPzPDI7u&kpPi&B-Sh z&h!+nBjSaw7^-e3GiuCIaCC)ZTu!{*-kU5;{e;j)lsS`D&@^b=WWjWITfX8w zDJjxuq>la%eYAY{NwonMOAw8U4pm8g8gnEBkCy6)D< zvbjksJC@p)w7rzn%-_maT-KklX+7Qcr9t$DV=!I%N1Sg*5k1Sa47&0Ao%)G=?%Le`XpmZ+FTaRE066xAgVG{lrKp5IM7+ zb=M&?4?kth<1OKj(AOB;eDWEuTOnaG7nU)_VHYn_T9oPef)y%<>@OMi^+GFp$92{? zgm3hC0M*SD_o&k`3wmS3jQgtKp|~eOfk-ZeqJya}R!5+?$cXQ$-KZF2SMoUCa5!qw za#5lpWls#*b(AN49KrCp?>~wtFXlRA^iwpkDuu%#2^Tg8J(Br<X{kBSu-ci|1lCqz{XS|;ahMwS z4;Z>a*rUd99#zJ^kE+Mj9LshyNod>E?zFgfeh`wWY7{xKwvYXf%rQ+13}l}y4@(ZD zu)*;kUHz}(i>u4+Yx8{)`F`>cu5wBM^s{?j>9sZ@@ySL5vI#h^Fnvv#z9Z-j!?m`t z$Dagx@|>e?iXbPvp48emEdU^X*Pnq&j)}l|G+9X~GE{#hkXTr$zXaREiAjQCrGNSs zWCHW+3tu`nxGPB1nM_E-)WHyO<;QvZ;8=@i*qR=049hDLTW`oDfugpfl3!kk9&1m@eRMKPG$!RB1iSPt;}X z4|({SNN6QuH?Rsmt>sR+of>7>hy=efNA_C&mnQ}3B_5pN05XvniZYHZ`Dxo1#wvv6 z!o=jt1^v@3@(KrLmmH7>`Z<%fif-Vr%XnB*JY0Iag!9MXfK7NmGwSA{6o4#SzNjBB z8q5Ql(I!gLu;?pbBbd6#f_x=*3Vh?>ZnQuTTX6#=Fi%5%0f^EQEt%~;QgH5bPbKZG zuURF+2W8C#1*4%|$68FZKIk3VA>0Sh*3|)(ptEuh-XMGRB?bYT|Sb@iJ#)$4`&a1f)2a-$(UP#Kc!NjI`C;c%A-OBWTISsZ60U_ zq#%}ePo6BEXd&_;DcH{AV*$2$qbL_$S82|I>Rqo;Q~y5-umqJ<9=Ld#%}1BL&5sFltD?2Xw&p_4UXM!Y|}ERhyE9h1ja*zq@mI} ztW}JxScJ0{<;w3>1nyjO_!tQ8TjwFu5i35B38mreGgzhZWClaQV|&mK6=mPL9X~~5 z06Ye`M$9JcwI;Eky;?tcA{F9xaKXSMOpcf^10tBS4G>e4CWQmAwv=4KrsRfa zEPQ07t`v5`n_S38k7?GrE--MB_0I?$Cc-3DR#@?%p%37Tuqbe%ykd@D@EtuD(f@0; z7sQ)2ls+9Fn&1ZGhmp1csR=nAi-wqdVOM(f($}=h!K`4qHNpV7QzI-F(vw8oK^7q3 z%v=C`HVSbVVRxHTFdgRE zbxrAYgPG`xxxS5N%hp2F-Jit$zKKrAu>V%p@>qz#znFb)ucI$R0?oxU}4Hj#)FO){9iel(oZnSDKgmIU(dQ4mYXY?pc zxrXBZin<+@iHcYVaH0Vjef>Gvn@94!E4te9@oT+QZqJ=c*F<5J;jcMVCI^CM z!2@X|dnRZ{A+z(5if(ZhP!PeO57hNWpr<8Yw%@V=(_2zS(KK@^V$x!$-{=;dPy}V> z=&nVv%ko3^L8PROVmd?n*eC7GkBh6v=x9v8p_xJ<3%wAs54~gExN!_3a6fpI)}PM; zQfn7eLpVoT9fNKjt;}-KM`uYmjE0sABWc$gjkj(_JOsJN(MLfu?cA7iq6wiH-C-2O zMY>Nc{i(C>0TIBXANHmiCajnEg(9C@Xo_msW6XiX@flQzp5wMNL^3+3Ox$yf(0&8h zgJNDkcdU_YafO${(fe>u$H;Yf@PNdQh>rhdGH?l*$nm6=!E6^1X@>LD!cmqjLDco> z0WB_Di4C6)NvVT)6Zk^Q1mna^RzD|H6iI9y6LSHpP}bWBY|eRFqc;LKA&l@9^fNII zIV)Uesb}sji{@?Tg#iL!0wHj93>K|hq^W~wtZeTwwl!s?ZvQ+Xrf0wv zjjaC2PR};58E7HS_xE}=q4SMfPM3h-mhs5g?;+pci%t5&EV}iLiIRhZG(?yf^xqRT zO?f|AxANlU@4yJ$KVaGctUR!9=lm_ZjEVS}3 z_`%%nX`KQnK(da`XEeWl7>K2}l*S?UhP#J7gUCli`&PY@h#GmsYnx6(GZBVAY{XG7 z3pd5oT%w`ro?FX<)@N%666nTxrJ0~O(e8y8yr6^23?k)32%51Mt0qd(EnphOh7t{B zh6La4UIS)bcD0XL;!Zb-{CO|jOlGFFbf=IHMv5B`(M$@yJvo+4k)C|A6>)1iPFu9D z@~b6nreQZte;ycpbfaUehA%zXR{P&(H1Edw3R0VBpBmpzCRi6Hjb)~EM)fKbKotBe z@v_qfJQ!Mwt{brFGqU*%)+jvaCZByqWsQPhgYpQ^7o~nJuPoh%gL%%R*&V{+>TBHJ z8>6`Fnau&IS7J6Hp4rX%5bnp}b)lano+j0%Y8azdLH=oc=8_W%eNm;dVcJmJ$c~<~ z8BJ+YJ!af@&fh}ZR)k_yz1nPQlk`_E;enuh`#Ll_bC)n#hjHE_62ge2_Z?ilP*kMm zTACrL&Ld^1Be0qsaZL$aiMhIt&z&ba9N0hB=T-@(d04uYi)yDv(QpC@fn!;k z^Tzs5!;f>t_=`o?d@TA{WRa&N70thqkzbUXRDaRJOqR-W97iE?q;nR-CG#X+- zeX-ayB3PPXLH{!o?IaepNM+v7P>AuYgfddr+o^JO^O$4~egfF8k@g5kn3scqP_A5O zG)nD&rjURZF|YSyPNp_xpGvElRNFzWExMLFXF0V5Rf+iHK3-pAEf;N7M;FHv>cGo> zn)mB^+^MMUFP&v&)#eklVzD9$zP@mz&D9DyIk!*aIMgFxrs4Cp><*0 zYB12VVslR$Q$$)AC+TRKF1j23V^D58sq&3f)?`^42NB&l$Lo#c)K>-O8jrhUG>ksY zWDI}O+{;XPS)e=UKMr$(S2eV<67OWtQ3}$Kk-J@VfD*oeeX&{%0-5!v8Y5g(=sbQM zd?Zt`Uoltic}hUMFUIT5Y*s@ox4%4ggYev|@)LhcK`rgKZfO(2H3$*)lK}}2M5+u1 z?=W91hS%)mytSs}UQcD=K1oC1`QE)g9mFKNOOKOm_`yCu#19(w+O-cP@fV|2xaEtp zuj{bxMQE+6;pbyw)>7ENW1BN3`8b+rD=1#~5k*l=uTk%5nP6xK_5oS*u6Tf7c;|QI zn#@tCp^*w41h@SRngTnvd4D%kMZ|y_r#k&>je=;uPw!UvEx2VmI(g(NefpfCX*=J& z444U+-N4ce)X9@cg@6YZY>`qgM0EV+!c?C{=n3b&n!=?=YhsPqIzbg<$N;6HJ|Q&* z{IGg;iZ&`9Td5B5m$40G=Ss4lN7*J4xMY$c!$el@C@auzzTtpa-UmTbFDV*WIbr_;o%RlTXVf(TbsNVf8AQj2EG0+GHk%O@+^WpR{-SUBRY^%)x9 zzwZMba0S8?34Qo~Br<+9ewLiTIFW&gQ&SW~2IwbWO+r8pL3$gpPkpL+gO(|(X%M@( zaupjayp{yD~5|$oA&>^sh$?M4O2YxL(}xSIUKg*kbGu zP~V@@>g#us@&C%xhA7wLP2wM?T9vk{P@E@-r<~~nsoPCh7M-SW+EG>|t&SDEowWM9 z-e|B^dfJ=pkR^Z)F84C})Q$v3qO{UETTM-<#|~Rs#LnJGQ9_5PmRT8PQG?Qg2>`^K z`jI*jQUY?GnLBP#-ovayo_mp1njpnOfJPuXAqtfBrUsF4p;#z23JBLqcd9W`z=53k zgcOu5D5Mn-nZ?DN#MJcXwwtL|lQ1n*Aedliw*GDN$*&+>zV|!sdOw0vPF{*(FP$r( z?@hYvr_$EJr7s+^PV|KmQF;rZ29CJpE&lVRSnFOk3p>`tMbCqvhVIy)1CnbItIXh| zw}vp%3ej6gr3=*B$l^6U?^V{>M?ls9pp~A(X8;>7P$+{f+7LTN$KEy&s)1w3XLG(X z4`Zx8B%{Z8FBi7zZP9A}N{24QBH=smRe8Ha5e`W)kqjhf0g6+U1%TS@1%pb!EOAsK zTc^gSHn^$LwJN~naK`UT!jVKURcRt>2stx_suy^USdN9{fTl3Z5E@}9VU$Qstfe0T zk|EI$dE}dX$Y_=`c^r4GAW5>&W@Spg5}|^`$a5uDDDAOp=zAMVo3L@^X7yT4NJXtn zN!65yA5#uQfXFXVda;ScP@B9!!KlYyngUv29{>OcZ2_#)$)5lKxza|~XM+nvInYgT z(nA^0nA_7

67*^ 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%0DX+>wB!Xu_Jl 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%0DTY*Ju{XMC(}@z03oIdq9{e*aJLp%h0U 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

|Z%`9+GY^OxaRTXjyxWz9M-4Zux2hoSK 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

3qYIvYk|5jzjm}8q%};M4ZCZMX;>Hm-dK(iG` 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 z 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 _Vhggz0ZBN(EG=I>i?SlP+lp$oJH8E~4vLH)w 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/Ie*xK0jTt&|i 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 ( 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

_*0FJ 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�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%0D3~tqn2y+UF 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

1;Aw0E11sMZ3!LbrJ25x0|C7VjP{D>! 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

4c2wHbbz0d(Ve`i|2D354>&J+K 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

ng4F_)5#puH=7A)Q)B1$tiTHEwOXb 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 hV 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 y<+{Jsv4X#V=v`!oAX+RAwt*94 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 z

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

13&g3EU&~S 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�Re$}4Z)?CstQo6| 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
  • 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 B91Q>f literal 0 HcmV?d00001 diff --git a/tests/unit/artifacts/test_generic_artifact.py b/tests/unit/artifacts/test_generic_artifact.py new file mode 100644 index 000000000..60121d22d --- /dev/null +++ b/tests/unit/artifacts/test_generic_artifact.py @@ -0,0 +1,27 @@ +import pytest + +from griptape.artifacts import BaseArtifact, GenericArtifact + + +class TestGenericArtifact: + @pytest.fixture() + def generic_artifact(self): + return GenericArtifact( + value="some generic data", + ) + + def test_to_text(self, generic_artifact: GenericArtifact): + assert generic_artifact.to_text() == "some generic data" + + def test_to_dict(self, generic_artifact: GenericArtifact): + generic_dict = generic_artifact.to_dict() + + assert generic_dict["value"] == "some generic data" + + def test_deserialization(self, generic_artifact): + artifact_dict = generic_artifact.to_dict() + deserialized_artifact = BaseArtifact.from_dict(artifact_dict) + + assert isinstance(deserialized_artifact, GenericArtifact) + + assert deserialized_artifact.value == "some generic data" diff --git a/tests/unit/common/test_prompt_stack.py b/tests/unit/common/test_prompt_stack.py index e69fe710d..8aba023bc 100644 --- a/tests/unit/common/test_prompt_stack.py +++ b/tests/unit/common/test_prompt_stack.py @@ -1,9 +1,10 @@ import pytest -from griptape.artifacts import ActionArtifact, ImageArtifact, ListArtifact, TextArtifact +from griptape.artifacts import ActionArtifact, GenericArtifact, ImageArtifact, ListArtifact, TextArtifact from griptape.common import ( ActionCallMessageContent, ActionResultMessageContent, + GenericMessageContent, ImageMessageContent, PromptStack, TextMessageContent, @@ -39,6 +40,10 @@ def test_add_message(self, prompt_stack): ), "role", ) + prompt_stack.add_message( + GenericArtifact("foo"), + "role", + ) assert prompt_stack.messages[0].role == "role" assert isinstance(prompt_stack.messages[0].content[0], TextMessageContent) @@ -76,6 +81,10 @@ def test_add_message(self, prompt_stack): assert isinstance(prompt_stack.messages[5].content[1], ActionResultMessageContent) assert prompt_stack.messages[5].content[1].artifact.value == "qux" + assert prompt_stack.messages[6].role == "role" + assert isinstance(prompt_stack.messages[6].content[0], GenericMessageContent) + assert prompt_stack.messages[6].content[0].artifact.value == "foo" + def test_add_system_message(self, prompt_stack): prompt_stack.add_system_message("foo") diff --git a/tests/unit/drivers/prompt/test_google_prompt_driver.py b/tests/unit/drivers/prompt/test_google_prompt_driver.py index 478ef8fb9..0dc797a74 100644 --- a/tests/unit/drivers/prompt/test_google_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_google_prompt_driver.py @@ -5,7 +5,7 @@ from google.generativeai.types import ContentDict, GenerationConfig from google.protobuf.json_format import MessageToDict -from griptape.artifacts import ActionArtifact, ImageArtifact, TextArtifact +from griptape.artifacts import ActionArtifact, GenericArtifact, ImageArtifact, TextArtifact from griptape.artifacts.list_artifact import ListArtifact from griptape.common import ActionCallDeltaMessageContent, PromptStack, TextDeltaMessageContent, ToolAction from griptape.drivers import GooglePromptDriver @@ -114,6 +114,7 @@ def prompt_stack(self, request): ] ) ) + prompt_stack.add_user_message(GenericArtifact("video-file")) return prompt_stack @@ -139,6 +140,7 @@ def messages(self): ], "role": "user", }, + {"parts": ["video-file"], "role": "user"}, ] def test_init(self): From 728ade31d44e39f0dbe35274df34814b54b3c4e3 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 18 Jul 2024 11:06:54 -0700 Subject: [PATCH 83/87] Add More Ruff (#996) --- .../contents/action_call_message_content.py | 6 ++--- .../amazon_s3_file_manager_driver.py | 4 +-- .../anthropic_image_query_driver.py | 4 +-- ...bedrock_claude_image_query_model_driver.py | 4 +-- ...loud_knowledge_base_vector_store_driver.py | 2 +- griptape/tasks/base_multi_text_input_task.py | 6 +++-- griptape/tasks/image_query_task.py | 6 +++-- pyproject.toml | 27 ++++++++++--------- ...mazon_sagemaker_jumpstart_prompt_driver.py | 4 +-- tests/unit/mixins/test_activity_mixin.py | 8 +++--- .../tasks/test_audio_transcription_task.py | 4 +-- tests/unit/tasks/test_image_query_task.py | 16 +++++------ .../test_inpainting_image_generation_task.py | 16 +++++------ .../test_outpainting_image_generation_task.py | 16 +++++------ .../test_prompt_image_generation_task.py | 4 +-- tests/unit/tasks/test_text_to_speech_task.py | 4 +-- .../test_variation_image_generation_task.py | 16 +++++------ 17 files changed, 77 insertions(+), 70 deletions(-) diff --git a/griptape/common/prompt_stack/contents/action_call_message_content.py b/griptape/common/prompt_stack/contents/action_call_message_content.py index e658af23d..94cc1cd14 100644 --- a/griptape/common/prompt_stack/contents/action_call_message_content.py +++ b/griptape/common/prompt_stack/contents/action_call_message_content.py @@ -23,7 +23,7 @@ def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> ActionCallMes tag = None name = None path = None - input = "" + json_input = "" for delta in action_call_deltas: if delta.tag is not None: @@ -33,11 +33,11 @@ def from_deltas(cls, deltas: Sequence[BaseDeltaMessageContent]) -> ActionCallMes if delta.path is not None: path = delta.path if delta.partial_input is not None: - input += delta.partial_input + json_input += delta.partial_input if tag is not None and name is not None and path is not None: try: - parsed_input = json.loads(input) + parsed_input = json.loads(json_input) except json.JSONDecodeError as exc: raise ValueError("Invalid JSON input for ToolAction") from exc action = ToolAction(tag=tag, name=name, path=path, input=parsed_input) diff --git a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py index 01eb1e21f..e58e46d37 100644 --- a/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py +++ b/griptape/drivers/file_manager/amazon_s3_file_manager_driver.py @@ -103,8 +103,8 @@ def _list_files_and_dirs(self, full_key: str, **kwargs) -> list[str]: for page in pages: for obj in page.get("CommonPrefixes", []): prefix = obj.get("Prefix") - dir = prefix[len(full_key) :].rstrip("/") - files_and_dirs.append(dir) + directory = prefix[len(full_key) :].rstrip("/") + files_and_dirs.append(directory) for obj in page.get("Contents", []): key = obj.get("Key") diff --git a/griptape/drivers/image_query/anthropic_image_query_driver.py b/griptape/drivers/image_query/anthropic_image_query_driver.py index 4d91b6ea5..bd19862ec 100644 --- a/griptape/drivers/image_query/anthropic_image_query_driver.py +++ b/griptape/drivers/image_query/anthropic_image_query_driver.py @@ -53,9 +53,9 @@ def _base_params(self, text_query: str, images: list[ImageArtifact]) -> dict: def _construct_image_message(self, image_data: ImageArtifact) -> dict: data = image_data.base64 - type = image_data.mime_type + media_type = image_data.mime_type - return {"source": {"data": data, "media_type": type, "type": "base64"}, "type": "image"} + return {"source": {"data": data, "media_type": media_type, "type": "base64"}, "type": "image"} def _construct_text_message(self, query: str) -> dict: return {"text": query, "type": "text"} diff --git a/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py b/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py index ccb902a81..8260ce3d5 100644 --- a/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py +++ b/griptape/drivers/image_query_model/bedrock_claude_image_query_model_driver.py @@ -29,9 +29,9 @@ def process_output(self, output: dict) -> TextArtifact: def _construct_image_message(self, image_data: ImageArtifact) -> dict: data = image_data.base64 - type = image_data.mime_type + media_type = image_data.mime_type - return {"source": {"data": data, "media_type": type, "type": "base64"}, "type": "image"} + return {"source": {"data": data, "media_type": media_type, "type": "base64"}, "type": "image"} def _construct_text_message(self, query: str) -> dict: return {"text": query, "type": "text"} diff --git a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py index e3bda9d4e..34b646846 100644 --- a/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -85,7 +85,7 @@ def query( include_vectors: Optional[bool] = None, distance_metric: Optional[str] = None, # GriptapeCloudKnowledgeBaseVectorStoreDriver-specific params: - filter: Optional[dict] = None, + filter: Optional[dict] = None, # noqa: A002 **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: """Performs a query on the Knowledge Base. diff --git a/griptape/tasks/base_multi_text_input_task.py b/griptape/tasks/base_multi_text_input_task.py index 2891e52d7..010ffa10c 100644 --- a/griptape/tasks/base_multi_text_input_task.py +++ b/griptape/tasks/base_multi_text_input_task.py @@ -25,7 +25,9 @@ def input(self) -> ListArtifact: if all(isinstance(elem, TextArtifact) for elem in self._input): return ListArtifact([artifact for artifact in self._input if isinstance(artifact, TextArtifact)]) elif all(isinstance(elem, Callable) for elem in self._input): - return ListArtifact([callable(self) for callable in self._input if isinstance(callable, Callable)]) + return ListArtifact( + [callable_input(self) for callable_input in self._input if isinstance(callable_input, Callable)] + ) else: return ListArtifact( [ @@ -45,7 +47,7 @@ def input( def before_run(self) -> None: super().before_run() - joined_input = "\n".join([input.to_text() for input in self.input]) + joined_input = "\n".join([i.to_text() for i in self.input]) self.structure.logger.info(f"{self.__class__.__name__} {self.id}\nInput: {joined_input}") def after_run(self) -> None: diff --git a/griptape/tasks/image_query_task.py b/griptape/tasks/image_query_task.py index 60a1c89c8..ea1b53739 100644 --- a/griptape/tasks/image_query_task.py +++ b/griptape/tasks/image_query_task.py @@ -78,8 +78,10 @@ def image_query_engine(self, value: ImageQueryEngine) -> None: def run(self) -> TextArtifact: query = self.input.value[0] - if all(isinstance(input, ImageArtifact) for input in self.input.value[1:]): - image_artifacts = [input for input in self.input.value[1:] if isinstance(input, ImageArtifact)] + if all(isinstance(artifact, ImageArtifact) for artifact in self.input.value[1:]): + image_artifacts = [ + image_artifact for image_artifact in self.input.value[1:] if isinstance(image_artifact, ImageArtifact) + ] else: raise ValueError("All inputs after the query must be ImageArtifacts.") diff --git a/pyproject.toml b/pyproject.toml index 1e7a7cf33..08b6ab618 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -222,26 +222,29 @@ line-length = 120 [tool.ruff.lint] select = [ + "F", # pyflakes "E", # pycodestyle-errors "W", # pycodestyle-warnings - "F", # Pyflakes + "C90", # mccabe + "I", # isort + "N", # pep8-naming + "D", # pydocstyle "UP", # pyupgrade + "YTT", # flake8-2020 + "ASYNC", # flake8-async + "ANN", # flake8-annotations + "FBT", # flake8-boolean-trap + "A", # flake8-builtins "B", # flake8-bugbear + "COM", # flake8-commas + "C4", # flake8-comprehensions + "FA", # flake8-future-annotations + "T20", # flake8-print + "PT", # flake8-pytest-style "SIM", # flake8-simplify "TID", # flake8-tidy-imports - "T20", # flake8-print - "C90", # mccabe "TCH", # flake8-type-checking - "D", # pydocstyle "PGH", # pygrep-hooks - "I", # isort - "FA", # flake8-future-annotations - "COM", # flake8-commas - "C4", # flake8-comprehensions - "ANN", # flake8-annotations - "FBT", # flake8-boolean-trap - "PT", # flake8-pytest-style - "N" # pep8-naming ] ignore = [ "UP007", # non-pep604-annotation diff --git a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py index e74797e42..c894524f5 100644 --- a/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py +++ b/tests/unit/drivers/prompt/test_amazon_sagemaker_jumpstart_prompt_driver.py @@ -11,9 +11,9 @@ def to_streaming_body(data: Any) -> StreamingBody: - bytes = json.dumps(data).encode("utf-8") + encoded_body = json.dumps(data).encode("utf-8") - return StreamingBody(BytesIO(bytes), len(bytes)) + return StreamingBody(BytesIO(encoded_body), len(encoded_body)) class TestAmazonSageMakerJumpstartPromptDriver: diff --git a/tests/unit/mixins/test_activity_mixin.py b/tests/unit/mixins/test_activity_mixin.py index 91e0c3a67..f31f9f0e8 100644 --- a/tests/unit/mixins/test_activity_mixin.py +++ b/tests/unit/mixins/test_activity_mixin.py @@ -74,10 +74,10 @@ def test_enable_activities(self, tool): assert len(tool.activities()) > 0 def test_activity_to_input(self, tool): - input = tool.activity_to_input(tool.test) - assert str(input) == str( + activity_input = tool.activity_to_input(tool.test) + assert str(activity_input) == str( {Literal("input", description=""): {"values": Schema({Literal("test"): str}, description="Test input")}} ) - input = tool.activity_to_input(tool.test_no_schema) - assert input == {Optional("input"): {}} + activity_input = tool.activity_to_input(tool.test_no_schema) + assert activity_input == {Optional("input"): {}} diff --git a/tests/unit/tasks/test_audio_transcription_task.py b/tests/unit/tasks/test_audio_transcription_task.py index f4bc0e8b8..734e111cf 100644 --- a/tests/unit/tasks/test_audio_transcription_task.py +++ b/tests/unit/tasks/test_audio_transcription_task.py @@ -25,10 +25,10 @@ def test_audio_input(self, audio_artifact, audio_transcription_engine): assert task.input.value == audio_artifact.value def test_callable_input(self, audio_artifact, audio_transcription_engine): - def callable(task: BaseTask) -> AudioArtifact: + def callable_input(task: BaseTask) -> AudioArtifact: return audio_artifact - task = AudioTranscriptionTask(callable, audio_transcription_engine=audio_transcription_engine) + task = AudioTranscriptionTask(callable_input, audio_transcription_engine=audio_transcription_engine) assert task.input == audio_artifact diff --git a/tests/unit/tasks/test_image_query_task.py b/tests/unit/tasks/test_image_query_task.py index 549009fc1..447faa01c 100644 --- a/tests/unit/tasks/test_image_query_task.py +++ b/tests/unit/tasks/test_image_query_task.py @@ -43,21 +43,21 @@ def test_artifact_inputs(self, text_artifact: TextArtifact, image_artifact: Imag assert task.input.value[2] == image_artifact def test_callable_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact, image_artifact] + artifacts = [text_artifact, image_artifact, image_artifact] - def callable(task: BaseTask) -> ListArtifact: - return ListArtifact(value=input) + def callable_input(task: BaseTask) -> ListArtifact: + return ListArtifact(value=artifacts) - task = ImageQueryTask(callable) + task = ImageQueryTask(callable_input) - assert task.input.value == input + assert task.input.value == artifacts def test_list_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact, image_artifact] + artifacts = [text_artifact, image_artifact, image_artifact] - task = ImageQueryTask(ListArtifact(value=input)) + task = ImageQueryTask(ListArtifact(value=artifacts)) - assert task.input.value == input + assert task.input.value == artifacts def test_config_image_generation_engine(self, text_artifact, image_artifact): task = ImageQueryTask((text_artifact, [image_artifact, image_artifact])) diff --git a/tests/unit/tasks/test_inpainting_image_generation_task.py b/tests/unit/tasks/test_inpainting_image_generation_task.py index ff287d79a..61c437bb7 100644 --- a/tests/unit/tasks/test_inpainting_image_generation_task.py +++ b/tests/unit/tasks/test_inpainting_image_generation_task.py @@ -27,20 +27,20 @@ def test_artifact_inputs(self, text_artifact: TextArtifact, image_artifact: Imag assert task.input.value == list(input_tuple) def test_callable_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact, image_artifact] + artifacts = [text_artifact, image_artifact, image_artifact] - def callable(task: BaseTask) -> ListArtifact: - return ListArtifact(value=list(input)) + def callable_input(task: BaseTask) -> ListArtifact: + return ListArtifact(value=list(artifacts)) - task = InpaintingImageGenerationTask(callable, image_generation_engine=Mock()) + task = InpaintingImageGenerationTask(callable_input, image_generation_engine=Mock()) - assert task.input.value == input + assert task.input.value == artifacts def test_list_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact] - task = InpaintingImageGenerationTask(ListArtifact(input), image_generation_engine=Mock()) + artifacts = [text_artifact, image_artifact] + task = InpaintingImageGenerationTask(ListArtifact(artifacts), image_generation_engine=Mock()) - assert task.input.value == input + assert task.input.value == artifacts def test_bad_input(self, image_artifact): with pytest.raises(ValueError): diff --git a/tests/unit/tasks/test_outpainting_image_generation_task.py b/tests/unit/tasks/test_outpainting_image_generation_task.py index 7de530330..593451120 100644 --- a/tests/unit/tasks/test_outpainting_image_generation_task.py +++ b/tests/unit/tasks/test_outpainting_image_generation_task.py @@ -27,20 +27,20 @@ def test_artifact_inputs(self, text_artifact: TextArtifact, image_artifact: Imag assert task.input.value == list(input_tuple) def test_callable_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact, image_artifact] + artifacts = [text_artifact, image_artifact, image_artifact] - def callable(task: BaseTask) -> ListArtifact: - return ListArtifact(input) + def callable_input(task: BaseTask) -> ListArtifact: + return ListArtifact(artifacts) - task = OutpaintingImageGenerationTask(callable, image_generation_engine=Mock()) + task = OutpaintingImageGenerationTask(callable_input, image_generation_engine=Mock()) - assert task.input.value == input + assert task.input.value == artifacts def test_list_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact] - task = OutpaintingImageGenerationTask(ListArtifact(input), image_generation_engine=Mock()) + artifacts = [text_artifact, image_artifact] + task = OutpaintingImageGenerationTask(ListArtifact(artifacts), image_generation_engine=Mock()) - assert task.input.value == input + assert task.input.value == artifacts def test_bad_input(self, image_artifact): with pytest.raises(ValueError): diff --git a/tests/unit/tasks/test_prompt_image_generation_task.py b/tests/unit/tasks/test_prompt_image_generation_task.py index c3add5720..1c4b639fb 100644 --- a/tests/unit/tasks/test_prompt_image_generation_task.py +++ b/tests/unit/tasks/test_prompt_image_generation_task.py @@ -19,10 +19,10 @@ def test_string_input(self): def test_callable_input(self): input_artifact = TextArtifact("some text input") - def callable(task: BaseTask) -> TextArtifact: + def callable_input(task: BaseTask) -> TextArtifact: return input_artifact - task = PromptImageGenerationTask(callable, image_generation_engine=Mock()) + task = PromptImageGenerationTask(callable_input, image_generation_engine=Mock()) assert task.input == input_artifact diff --git a/tests/unit/tasks/test_text_to_speech_task.py b/tests/unit/tasks/test_text_to_speech_task.py index 86bc1d2ce..bf1f19d5a 100644 --- a/tests/unit/tasks/test_text_to_speech_task.py +++ b/tests/unit/tasks/test_text_to_speech_task.py @@ -17,10 +17,10 @@ def test_string_input(self): def test_callable_input(self): input_artifact = TextArtifact("some text input") - def callable(task: BaseTask) -> TextArtifact: + def callable_input(task: BaseTask) -> TextArtifact: return input_artifact - task = TextToSpeechTask(callable, text_to_speech_engine=Mock()) + task = TextToSpeechTask(callable_input, text_to_speech_engine=Mock()) assert task.input == input_artifact diff --git a/tests/unit/tasks/test_variation_image_generation_task.py b/tests/unit/tasks/test_variation_image_generation_task.py index 3f865931f..a910fb8e0 100644 --- a/tests/unit/tasks/test_variation_image_generation_task.py +++ b/tests/unit/tasks/test_variation_image_generation_task.py @@ -27,20 +27,20 @@ def test_artifact_inputs(self, text_artifact: TextArtifact, image_artifact: Imag assert task.input.value == list(input_tuple) def test_callable_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact] + artifacts = [text_artifact, image_artifact] - def callable(task: BaseTask) -> ListArtifact: - return ListArtifact(input) + def callable_input(task: BaseTask) -> ListArtifact: + return ListArtifact(artifacts) - task = VariationImageGenerationTask(callable, image_generation_engine=Mock()) + task = VariationImageGenerationTask(callable_input, image_generation_engine=Mock()) - assert task.input.value == input + assert task.input.value == artifacts def test_list_input(self, text_artifact: TextArtifact, image_artifact: ImageArtifact): - input = [text_artifact, image_artifact] - task = VariationImageGenerationTask(ListArtifact(input), image_generation_engine=Mock()) + artifact_input = [text_artifact, image_artifact] + task = VariationImageGenerationTask(ListArtifact(artifact_input), image_generation_engine=Mock()) - assert task.input.value == input + assert task.input.value == artifact_input def test_bad_input(self, image_artifact): with pytest.raises(ValueError): From 331a36b0a4f7cbfc2b954d243b1a5ade9d081df9 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 18 Jul 2024 11:42:49 -0700 Subject: [PATCH 84/87] Fix cohere link (#994) --- .../drivers/prompt-drivers.md | 30 +++++-------------- docs/griptape-framework/misc/events.md | 2 +- docs/griptape-framework/tools/index.md | 5 +++- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/docs/griptape-framework/drivers/prompt-drivers.md b/docs/griptape-framework/drivers/prompt-drivers.md index bc6142d3d..a438e985e 100644 --- a/docs/griptape-framework/drivers/prompt-drivers.md +++ b/docs/griptape-framework/drivers/prompt-drivers.md @@ -56,15 +56,10 @@ print(result.value) Griptape offers the following Prompt Drivers for interacting with LLMs. -!!! warning - When overriding a default Prompt Driver, take care to ensure you've updated the Structure's configured Embedding Driver as well. If Task Memory isn't needed, you can avoid compatibility issues by setting `task_memory=None` to disable Task Memory in your Structure. - ### OpenAI Chat -!!! info - This driver uses [OpenAi function calling](https://platform.openai.com/docs/guides/function-calling) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. - The [OpenAiChatPromptDriver](../../reference/griptape/drivers/prompt/openai_chat_prompt_driver.md) connects to the [OpenAI Chat](https://platform.openai.com/docs/guides/chat) API. +This driver uses [OpenAi function calling](https://platform.openai.com/docs/guides/function-calling) when using [Tools](../tools/index.md). ```python import os @@ -126,10 +121,8 @@ agent.run("How do I init and update a git submodule?") ### Azure OpenAI Chat -!!! info - This driver uses [Azure OpenAi function calling](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/function-calling) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. - The [AzureOpenAiChatPromptDriver](../../reference/griptape/drivers/prompt/azure_openai_chat_prompt_driver.md) connects to Azure OpenAI [Chat Completion](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/reference) APIs. +This driver uses [Azure OpenAi function calling](https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/function-calling) when using [Tools](../tools/index.md). ```python import os @@ -160,14 +153,12 @@ agent.run("Artificial intelligence is a technology with great promise.") ### Cohere -The [CoherePromptDriver](../../reference/griptape/drivers/prompt/cohere_prompt_driver.md) connects to the Cohere [Generate](https://docs.cohere.ai/reference/generate) API. +The [CoherePromptDriver](../../reference/griptape/drivers/prompt/cohere_prompt_driver.md) connects to the Cohere [Chat](https://docs.cohere.com/docs/chat-api) API. +This driver uses [Cohere tool use](https://docs.cohere.com/docs/tools) when using [Tools](../tools/index.md). !!! info This driver requires the `drivers-prompt-cohere` [extra](../index.md#extras). -!!! info - This driver uses [Cohere tool use](https://docs.cohere.com/docs/tools) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. - ```python import os from griptape.structures import Agent @@ -191,10 +182,8 @@ agent.run('What is the sentiment of this review? Review: "I really enjoyed this !!! info This driver requires the `drivers-prompt-anthropic` [extra](../index.md#extras). -!!! info - This driver uses [Anthropic tool use](https://docs.anthropic.com/en/docs/build-with-claude/tool-use) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. - The [AnthropicPromptDriver](../../reference/griptape/drivers/prompt/anthropic_prompt_driver.md) connects to the Anthropic [Messages](https://docs.anthropic.com/claude/reference/messages_post) API. +This driver uses [Anthropic tool use](https://docs.anthropic.com/en/docs/build-with-claude/tool-use) when using [Tools](../tools/index.md). ```python import os @@ -219,10 +208,8 @@ agent.run('Where is the best place to see cherry blossums in Japan?') !!! info This driver requires the `drivers-prompt-google` [extra](../index.md#extras). -!!! info - This driver uses [Gemini function calling](https://ai.google.dev/gemini-api/docs/function-calling) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. - The [GooglePromptDriver](../../reference/griptape/drivers/prompt/google_prompt_driver.md) connects to the [Google Generative AI](https://ai.google.dev/tutorials/python_quickstart#generate_text_from_text_inputs) API. +This driver uses [Gemini function calling](https://ai.google.dev/gemini-api/docs/function-calling) when using [Tools](../tools/index.md). ```python import os @@ -247,10 +234,8 @@ agent.run('Briefly explain how a computer works to a young child.') !!! info This driver requires the `drivers-prompt-amazon-bedrock` [extra](../index.md#extras). -!!! info - This drivers uses [Bedrock tool use](https://docs.aws.amazon.com/bedrock/latest/userguide/tool-use.html) when using [Tools](../tools/index.md). You can change this to use Griptape's own tool calling implementation by setting `use_native_tools` to `False`. - The [AmazonBedrockPromptDriver](../../reference/griptape/drivers/prompt/amazon_bedrock_prompt_driver.md) uses [Amazon Bedrock](https://aws.amazon.com/bedrock/)'s [Converse API](https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html). +This driver uses [Bedrock tool use](https://docs.aws.amazon.com/bedrock/latest/userguide/tool-use.html) when using [Tools](../tools/index.md). All models supported by the Converse API are available for use with this driver. @@ -316,7 +301,6 @@ agent.run("What color is the sky at different times of the day?") The [HuggingFaceHubPromptDriver](../../reference/griptape/drivers/prompt/huggingface_hub_prompt_driver.md) connects to the [Hugging Face Hub API](https://huggingface.co/docs/hub/api). - !!! warning Not all models featured on the Hugging Face Hub are supported by this driver. Models that are not supported by [Hugging Face serverless inference](https://huggingface.co/docs/api-inference/en/index) will not work with this driver. diff --git a/docs/griptape-framework/misc/events.md b/docs/griptape-framework/misc/events.md index 851b5f382..dff54ec4e 100644 --- a/docs/griptape-framework/misc/events.md +++ b/docs/griptape-framework/misc/events.md @@ -171,7 +171,7 @@ pipeline.config.prompt_driver.stream = True pipeline.add_tasks(ToolkitTask("Based on https://griptape.ai, tell me what griptape is.", tools=[WebScraper(off_prompt=True), TaskMemoryClient(off_prompt=False)])) for artifact in Stream(pipeline).run(): - print(artifact.value, end="", flush=True), + print(artifact.value, end="", flush=True) ``` diff --git a/docs/griptape-framework/tools/index.md b/docs/griptape-framework/tools/index.md index 05fc94501..fecfd6cd7 100644 --- a/docs/griptape-framework/tools/index.md +++ b/docs/griptape-framework/tools/index.md @@ -1,7 +1,10 @@ ## Overview One of the most powerful features of Griptape is the ability to use tools that can interact with the outside world. -Many of our [Prompt Drivers](../drivers/prompt-drivers.md) leverage the native function calling built into the LLMs. For LLMs that don't support this, Griptape provides its own implementation using the [ReAct](https://arxiv.org/abs/2210.03629) technique. +Many of our [Prompt Drivers](../drivers/prompt-drivers.md) leverage the native function calling built into the LLMs. +For LLMs that don't support this, Griptape provides its own implementation using the [ReAct](https://arxiv.org/abs/2210.03629) technique. + +You can switch between the two strategies by setting `use_native_tools` to `True` (LLM-native tool calling) or `False` (Griptape tool calling) on your [Prompt Driver][../drivers/prompt-drivers.md]. ## Tools Here is an example of a Pipeline using Tools: From 4dc5ae06a3db74b4be7ee24b273be228a12812c8 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Thu, 18 Jul 2024 16:29:22 -0700 Subject: [PATCH 85/87] Migrate to sqlalchemy 2, make sqlalchemy an optional dependency (#1000) --- CHANGELOG.md | 4 + griptape/drivers/sql/sql_driver.py | 17 +- .../vector/pgvector_vector_store_driver.py | 9 +- poetry.lock | 167 +++++++++--------- pyproject.toml | 16 +- 5 files changed, 105 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79e3dd5db..b4b813a2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: `EventListener.publish_event`'s `flush` argument is now a keyword-only argument. - **BREAKING**: `BaseEventListenerDriver.publish_event`'s `flush` argument is now a keyword-only argument. - **BREAKING**: Renamed `DummyException` to `DummyError` for pep8 naming compliance. +- **BREAKING**: Migrate to `sqlalchemy` 2.0. +- **BREAKING**: Make `sqlalchemy` an optional dependency. +- **BREAKING**: Rename `drivers-sql-redshift` to `drivers-sql-amazon-redshift` +- Removed unnecessary `sqlalchemy-redshift` dependency in `drivers-sql-amazon-redshift` extra. - Removed unnecessary `transformers` dependency in `drivers-prompt-huggingface` extra. - Removed unnecessary `huggingface-hub` dependency in `drivers-prompt-huggingface-pipeline` extra. diff --git a/griptape/drivers/sql/sql_driver.py b/griptape/drivers/sql/sql_driver.py index 5a3a4f5b2..0e3d1d4b7 100644 --- a/griptape/drivers/sql/sql_driver.py +++ b/griptape/drivers/sql/sql_driver.py @@ -33,28 +33,23 @@ def execute_query(self, query: str) -> Optional[list[BaseSqlDriver.RowResult]]: def execute_query_raw(self, query: str) -> Optional[list[dict[str, Optional[Any]]]]: sqlalchemy = import_optional_dependency("sqlalchemy") - with self.engine.begin() as con: + with self.engine.connect() as con: results = con.execute(sqlalchemy.text(query)) if results is not None: if results.returns_rows: - return [dict(result.items()) for result in results] + return [dict(result._mapping) for result in results] else: - return None + con.commit() else: raise ValueError("No result found") def get_table_schema(self, table_name: str, schema: Optional[str] = None) -> Optional[str]: sqlalchemy = import_optional_dependency("sqlalchemy") + sqlalchemy_exc = import_optional_dependency("sqlalchemy.exc") try: - table = sqlalchemy.Table( - table_name, - sqlalchemy.MetaData(bind=self.engine), - schema=schema, - autoload=True, - autoload_with=self.engine, - ) + table = sqlalchemy.Table(table_name, sqlalchemy.MetaData(), schema=schema, autoload_with=self.engine) return str([(c.name, c.type) for c in table.columns]) - except sqlalchemy.exc.NoSuchTableError: + except sqlalchemy_exc.NoSuchTableError: return None diff --git a/griptape/drivers/vector/pgvector_vector_store_driver.py b/griptape/drivers/vector/pgvector_vector_store_driver.py index ec266030a..0dbf96d9c 100644 --- a/griptape/drivers/vector/pgvector_vector_store_driver.py +++ b/griptape/drivers/vector/pgvector_vector_store_driver.py @@ -11,6 +11,7 @@ from sqlalchemy.engine import Engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import Session +from sqlalchemy.sql import text from griptape.drivers import BaseVectorStoreDriver from griptape.utils import import_optional_dependency @@ -58,6 +59,8 @@ def validate_engine(self, _: Attribute, engine: Optional[Engine]) -> None: def __attrs_post_init__(self) -> None: if self.engine is None: + if self.connection_string is None: + raise ValueError("An engine or connection string is required") self.engine = cast(Engine, create_engine(self.connection_string, **self.create_engine_params)) def setup( @@ -69,10 +72,12 @@ def setup( ) -> None: """Provides a mechanism to initialize the database schema and extensions.""" if install_uuid_extension: - self.engine.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";') + with self.engine.begin() as conn: + conn.execute(text('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";')) if install_vector_extension: - self.engine.execute('CREATE EXTENSION IF NOT EXISTS "vector";') + with self.engine.begin() as conn: + conn.execute(text('CREATE EXTENSION IF NOT EXISTS "vector";')) if create_schema: self._model.metadata.create_all(self.engine) diff --git a/poetry.lock b/poetry.lock index 3ae72743c..322b71d92 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1736,7 +1736,7 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"] name = "greenlet" version = "3.0.3" description = "Lightweight in-process concurrent programming" -optional = false +optional = true python-versions = ">=3.7" files = [ {file = "greenlet-3.0.3-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9da2bd29ed9e4f15955dd1595ad7bc9320308a3b766ef7f837e23ad4b4aac31a"}, @@ -4868,7 +4868,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -5575,18 +5574,18 @@ secure-local-storage = ["keyring (>=23.1.0,<25.0.0)"] [[package]] name = "snowflake-sqlalchemy" -version = "1.5.3" +version = "1.6.1" description = "Snowflake SQLAlchemy Dialect" optional = true python-versions = ">=3.8" files = [ - {file = "snowflake_sqlalchemy-1.5.3-py3-none-any.whl", hash = "sha256:0a4aa3f391797b22dd7658892f906191fd1d44870503ae7ca9278cddce6e5b89"}, - {file = "snowflake_sqlalchemy-1.5.3.tar.gz", hash = "sha256:79191ec3febfb32bcffecd66f2a7dd561bd571345ea4bccbf41cc1fb5c0682ff"}, + {file = "snowflake_sqlalchemy-1.6.1-py3-none-any.whl", hash = "sha256:06f5eac0f864f5634e7bcec4b87cdb77044723b9135c02bab426ba15382effee"}, + {file = "snowflake_sqlalchemy-1.6.1.tar.gz", hash = "sha256:792cde928c0d1d30714b88b0404de81ed297a7745cbcc253dcda973f65759382"}, ] [package.dependencies] snowflake-connector-python = "<4.0.0" -sqlalchemy = ">=1.4.19,<2.0.0" +sqlalchemy = ">=1.4.19" [package.extras] development = ["mock", "numpy", "pre-commit", "pytest", "pytest-cov", "pytest-rerunfailures", "pytest-timeout", "pytz"] @@ -5616,98 +5615,91 @@ files = [ [[package]] name = "sqlalchemy" -version = "1.4.52" +version = "2.0.31" description = "Database Abstraction Library" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +optional = true +python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-1.4.52-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:f68016f9a5713684c1507cc37133c28035f29925c75c0df2f9d0f7571e23720a"}, - {file = "SQLAlchemy-1.4.52-cp310-cp310-manylinux1_x86_64.manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_5_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24bb0f81fbbb13d737b7f76d1821ec0b117ce8cbb8ee5e8641ad2de41aa916d3"}, - {file = "SQLAlchemy-1.4.52-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e93983cc0d2edae253b3f2141b0a3fb07e41c76cd79c2ad743fc27eb79c3f6db"}, - {file = "SQLAlchemy-1.4.52-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:84e10772cfc333eb08d0b7ef808cd76e4a9a30a725fb62a0495877a57ee41d81"}, - {file = "SQLAlchemy-1.4.52-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:427988398d2902de042093d17f2b9619a5ebc605bf6372f7d70e29bde6736842"}, - {file = "SQLAlchemy-1.4.52-cp310-cp310-win32.whl", hash = "sha256:1296f2cdd6db09b98ceb3c93025f0da4835303b8ac46c15c2136e27ee4d18d94"}, - {file = "SQLAlchemy-1.4.52-cp310-cp310-win_amd64.whl", hash = "sha256:80e7f697bccc56ac6eac9e2df5c98b47de57e7006d2e46e1a3c17c546254f6ef"}, - {file = "SQLAlchemy-1.4.52-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2f251af4c75a675ea42766880ff430ac33291c8d0057acca79710f9e5a77383d"}, - {file = "SQLAlchemy-1.4.52-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb8f9e4c4718f111d7b530c4e6fb4d28f9f110eb82e7961412955b3875b66de0"}, - {file = "SQLAlchemy-1.4.52-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afb1672b57f58c0318ad2cff80b384e816735ffc7e848d8aa51e0b0fc2f4b7bb"}, - {file = "SQLAlchemy-1.4.52-cp311-cp311-win32.whl", hash = "sha256:6e41cb5cda641f3754568d2ed8962f772a7f2b59403b95c60c89f3e0bd25f15e"}, - {file = "SQLAlchemy-1.4.52-cp311-cp311-win_amd64.whl", hash = "sha256:5bed4f8c3b69779de9d99eb03fd9ab67a850d74ab0243d1be9d4080e77b6af12"}, - {file = "SQLAlchemy-1.4.52-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:49e3772eb3380ac88d35495843daf3c03f094b713e66c7d017e322144a5c6b7c"}, - {file = "SQLAlchemy-1.4.52-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:618827c1a1c243d2540314c6e100aee7af09a709bd005bae971686fab6723554"}, - {file = "SQLAlchemy-1.4.52-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de9acf369aaadb71a725b7e83a5ef40ca3de1cf4cdc93fa847df6b12d3cd924b"}, - {file = "SQLAlchemy-1.4.52-cp312-cp312-win32.whl", hash = "sha256:763bd97c4ebc74136ecf3526b34808c58945023a59927b416acebcd68d1fc126"}, - {file = "SQLAlchemy-1.4.52-cp312-cp312-win_amd64.whl", hash = "sha256:f12aaf94f4d9679ca475975578739e12cc5b461172e04d66f7a3c39dd14ffc64"}, - {file = "SQLAlchemy-1.4.52-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:853fcfd1f54224ea7aabcf34b227d2b64a08cbac116ecf376907968b29b8e763"}, - {file = "SQLAlchemy-1.4.52-cp36-cp36m-manylinux1_x86_64.manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_5_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f98dbb8fcc6d1c03ae8ec735d3c62110949a3b8bc6e215053aa27096857afb45"}, - {file = "SQLAlchemy-1.4.52-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e135fff2e84103bc15c07edd8569612ce317d64bdb391f49ce57124a73f45c5"}, - {file = "SQLAlchemy-1.4.52-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5b5de6af8852500d01398f5047d62ca3431d1e29a331d0b56c3e14cb03f8094c"}, - {file = "SQLAlchemy-1.4.52-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3491c85df263a5c2157c594f54a1a9c72265b75d3777e61ee13c556d9e43ffc9"}, - {file = "SQLAlchemy-1.4.52-cp36-cp36m-win32.whl", hash = "sha256:427c282dd0deba1f07bcbf499cbcc9fe9a626743f5d4989bfdfd3ed3513003dd"}, - {file = "SQLAlchemy-1.4.52-cp36-cp36m-win_amd64.whl", hash = "sha256:ca5ce82b11731492204cff8845c5e8ca1a4bd1ade85e3b8fcf86e7601bfc6a39"}, - {file = "SQLAlchemy-1.4.52-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:29d4247313abb2015f8979137fe65f4eaceead5247d39603cc4b4a610936cd2b"}, - {file = "SQLAlchemy-1.4.52-cp37-cp37m-manylinux1_x86_64.manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_5_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a752bff4796bf22803d052d4841ebc3c55c26fb65551f2c96e90ac7c62be763a"}, - {file = "SQLAlchemy-1.4.52-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7ea11727feb2861deaa293c7971a4df57ef1c90e42cb53f0da40c3468388000"}, - {file = "SQLAlchemy-1.4.52-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d913f8953e098ca931ad7f58797f91deed26b435ec3756478b75c608aa80d139"}, - {file = "SQLAlchemy-1.4.52-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a251146b921725547ea1735b060a11e1be705017b568c9f8067ca61e6ef85f20"}, - {file = "SQLAlchemy-1.4.52-cp37-cp37m-win32.whl", hash = "sha256:1f8e1c6a6b7f8e9407ad9afc0ea41c1f65225ce505b79bc0342159de9c890782"}, - {file = "SQLAlchemy-1.4.52-cp37-cp37m-win_amd64.whl", hash = "sha256:346ed50cb2c30f5d7a03d888e25744154ceac6f0e6e1ab3bc7b5b77138d37710"}, - {file = "SQLAlchemy-1.4.52-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:4dae6001457d4497736e3bc422165f107ecdd70b0d651fab7f731276e8b9e12d"}, - {file = "SQLAlchemy-1.4.52-cp38-cp38-manylinux1_x86_64.manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_5_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5d2e08d79f5bf250afb4a61426b41026e448da446b55e4770c2afdc1e200fce"}, - {file = "SQLAlchemy-1.4.52-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bbce5dd7c7735e01d24f5a60177f3e589078f83c8a29e124a6521b76d825b85"}, - {file = "SQLAlchemy-1.4.52-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:bdb7b4d889631a3b2a81a3347c4c3f031812eb4adeaa3ee4e6b0d028ad1852b5"}, - {file = "SQLAlchemy-1.4.52-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c294ae4e6bbd060dd79e2bd5bba8b6274d08ffd65b58d106394cb6abbf35cf45"}, - {file = "SQLAlchemy-1.4.52-cp38-cp38-win32.whl", hash = "sha256:bcdfb4b47fe04967669874fb1ce782a006756fdbebe7263f6a000e1db969120e"}, - {file = "SQLAlchemy-1.4.52-cp38-cp38-win_amd64.whl", hash = "sha256:7d0dbc56cb6af5088f3658982d3d8c1d6a82691f31f7b0da682c7b98fa914e91"}, - {file = "SQLAlchemy-1.4.52-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:a551d5f3dc63f096ed41775ceec72fdf91462bb95abdc179010dc95a93957800"}, - {file = "SQLAlchemy-1.4.52-cp39-cp39-manylinux1_x86_64.manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_5_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ab773f9ad848118df7a9bbabca53e3f1002387cdbb6ee81693db808b82aaab0"}, - {file = "SQLAlchemy-1.4.52-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2de46f5d5396d5331127cfa71f837cca945f9a2b04f7cb5a01949cf676db7d1"}, - {file = "SQLAlchemy-1.4.52-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7027be7930a90d18a386b25ee8af30514c61f3852c7268899f23fdfbd3107181"}, - {file = "SQLAlchemy-1.4.52-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99224d621affbb3c1a4f72b631f8393045f4ce647dd3262f12fe3576918f8bf3"}, - {file = "SQLAlchemy-1.4.52-cp39-cp39-win32.whl", hash = "sha256:c124912fd4e1bb9d1e7dc193ed482a9f812769cb1e69363ab68e01801e859821"}, - {file = "SQLAlchemy-1.4.52-cp39-cp39-win_amd64.whl", hash = "sha256:2c286fab42e49db23c46ab02479f328b8bdb837d3e281cae546cc4085c83b680"}, - {file = "SQLAlchemy-1.4.52.tar.gz", hash = "sha256:80e63bbdc5217dad3485059bdf6f65a7d43f33c8bde619df5c220edf03d87296"}, -] - -[package.dependencies] -greenlet = {version = "!=0.4.17", markers = "python_version >= \"3\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} + {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f2a213c1b699d3f5768a7272de720387ae0122f1becf0901ed6eaa1abd1baf6c"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9fea3d0884e82d1e33226935dac990b967bef21315cbcc894605db3441347443"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ad7f221d8a69d32d197e5968d798217a4feebe30144986af71ada8c548e9fa"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2bee229715b6366f86a95d497c347c22ddffa2c7c96143b59a2aa5cc9eebbc"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cd5b94d4819c0c89280b7c6109c7b788a576084bf0a480ae17c227b0bc41e109"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:750900a471d39a7eeba57580b11983030517a1f512c2cb287d5ad0fcf3aebd58"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-win32.whl", hash = "sha256:7bd112be780928c7f493c1a192cd8c5fc2a2a7b52b790bc5a84203fb4381c6be"}, + {file = "SQLAlchemy-2.0.31-cp310-cp310-win_amd64.whl", hash = "sha256:5a48ac4d359f058474fadc2115f78a5cdac9988d4f99eae44917f36aa1476327"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f68470edd70c3ac3b6cd5c2a22a8daf18415203ca1b036aaeb9b0fb6f54e8298"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2e2c38c2a4c5c634fe6c3c58a789712719fa1bf9b9d6ff5ebfce9a9e5b89c1ca"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd15026f77420eb2b324dcb93551ad9c5f22fab2c150c286ef1dc1160f110203"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2196208432deebdfe3b22185d46b08f00ac9d7b01284e168c212919891289396"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:352b2770097f41bff6029b280c0e03b217c2dcaddc40726f8f53ed58d8a85da4"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:56d51ae825d20d604583f82c9527d285e9e6d14f9a5516463d9705dab20c3740"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-win32.whl", hash = "sha256:6e2622844551945db81c26a02f27d94145b561f9d4b0c39ce7bfd2fda5776dac"}, + {file = "SQLAlchemy-2.0.31-cp311-cp311-win_amd64.whl", hash = "sha256:ccaf1b0c90435b6e430f5dd30a5aede4764942a695552eb3a4ab74ed63c5b8d3"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3b74570d99126992d4b0f91fb87c586a574a5872651185de8297c6f90055ae42"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6f77c4f042ad493cb8595e2f503c7a4fe44cd7bd59c7582fd6d78d7e7b8ec52c"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd1591329333daf94467e699e11015d9c944f44c94d2091f4ac493ced0119449"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74afabeeff415e35525bf7a4ecdab015f00e06456166a2eba7590e49f8db940e"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b9c01990d9015df2c6f818aa8f4297d42ee71c9502026bb074e713d496e26b67"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:66f63278db425838b3c2b1c596654b31939427016ba030e951b292e32b99553e"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-win32.whl", hash = "sha256:0b0f658414ee4e4b8cbcd4a9bb0fd743c5eeb81fc858ca517217a8013d282c96"}, + {file = "SQLAlchemy-2.0.31-cp312-cp312-win_amd64.whl", hash = "sha256:fa4b1af3e619b5b0b435e333f3967612db06351217c58bfb50cee5f003db2a5a"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:f43e93057cf52a227eda401251c72b6fbe4756f35fa6bfebb5d73b86881e59b0"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d337bf94052856d1b330d5fcad44582a30c532a2463776e1651bd3294ee7e58b"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c06fb43a51ccdff3b4006aafee9fcf15f63f23c580675f7734245ceb6b6a9e05"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:b6e22630e89f0e8c12332b2b4c282cb01cf4da0d26795b7eae16702a608e7ca1"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:79a40771363c5e9f3a77f0e28b3302801db08040928146e6808b5b7a40749c88"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-win32.whl", hash = "sha256:501ff052229cb79dd4c49c402f6cb03b5a40ae4771efc8bb2bfac9f6c3d3508f"}, + {file = "SQLAlchemy-2.0.31-cp37-cp37m-win_amd64.whl", hash = "sha256:597fec37c382a5442ffd471f66ce12d07d91b281fd474289356b1a0041bdf31d"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:dc6d69f8829712a4fd799d2ac8d79bdeff651c2301b081fd5d3fe697bd5b4ab9"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:23b9fbb2f5dd9e630db70fbe47d963c7779e9c81830869bd7d137c2dc1ad05fb"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a21c97efcbb9f255d5c12a96ae14da873233597dfd00a3a0c4ce5b3e5e79704"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a6a9837589c42b16693cf7bf836f5d42218f44d198f9343dd71d3164ceeeac"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc251477eae03c20fae8db9c1c23ea2ebc47331bcd73927cdcaecd02af98d3c3"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2fd17e3bb8058359fa61248c52c7b09a97cf3c820e54207a50af529876451808"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-win32.whl", hash = "sha256:c76c81c52e1e08f12f4b6a07af2b96b9b15ea67ccdd40ae17019f1c373faa227"}, + {file = "SQLAlchemy-2.0.31-cp38-cp38-win_amd64.whl", hash = "sha256:4b600e9a212ed59355813becbcf282cfda5c93678e15c25a0ef896b354423238"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b6cf796d9fcc9b37011d3f9936189b3c8074a02a4ed0c0fbbc126772c31a6d4"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:78fe11dbe37d92667c2c6e74379f75746dc947ee505555a0197cfba9a6d4f1a4"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc47dc6185a83c8100b37acda27658fe4dbd33b7d5e7324111f6521008ab4fe"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a41514c1a779e2aa9a19f67aaadeb5cbddf0b2b508843fcd7bafdf4c6864005"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:afb6dde6c11ea4525318e279cd93c8734b795ac8bb5dda0eedd9ebaca7fa23f1"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3f9faef422cfbb8fd53716cd14ba95e2ef655400235c3dfad1b5f467ba179c8c"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-win32.whl", hash = "sha256:fc6b14e8602f59c6ba893980bea96571dd0ed83d8ebb9c4479d9ed5425d562e9"}, + {file = "SQLAlchemy-2.0.31-cp39-cp39-win_amd64.whl", hash = "sha256:3cb8a66b167b033ec72c3812ffc8441d4e9f5f78f5e31e54dcd4c90a4ca5bebc"}, + {file = "SQLAlchemy-2.0.31-py3-none-any.whl", hash = "sha256:69f3e3c08867a8e4856e92d7afb618b95cdee18e0bc1647b77599722c9a28911"}, + {file = "SQLAlchemy-2.0.31.tar.gz", hash = "sha256:b607489dd4a54de56984a0c7656247504bd5523d9d0ba799aef59d4add009484"}, +] + +[package.dependencies] +greenlet = {version = "!=0.4.17", markers = "python_version < \"3.13\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"} +typing-extensions = ">=4.6.0" [package.extras] aiomysql = ["aiomysql (>=0.2.0)", "greenlet (!=0.4.17)"] +aioodbc = ["aioodbc", "greenlet (!=0.4.17)"] aiosqlite = ["aiosqlite", "greenlet (!=0.4.17)", "typing_extensions (!=3.10.0.1)"] asyncio = ["greenlet (!=0.4.17)"] -asyncmy = ["asyncmy (>=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] -mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2)"] +asyncmy = ["asyncmy (>=0.2.3,!=0.2.4,!=0.2.6)", "greenlet (!=0.4.17)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2,!=1.1.5)"] mssql = ["pyodbc"] mssql-pymssql = ["pymssql"] mssql-pyodbc = ["pyodbc"] -mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] -mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] +mypy = ["mypy (>=0.910)"] +mysql = ["mysqlclient (>=1.4.0)"] mysql-connector = ["mysql-connector-python"] -oracle = ["cx_oracle (>=7)", "cx_oracle (>=7,<8)"] +oracle = ["cx_oracle (>=8)"] +oracle-oracledb = ["oracledb (>=1.0.1)"] postgresql = ["psycopg2 (>=2.7)"] postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] -postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"] +postgresql-pg8000 = ["pg8000 (>=1.29.1)"] +postgresql-psycopg = ["psycopg (>=3.0.7)"] postgresql-psycopg2binary = ["psycopg2-binary"] postgresql-psycopg2cffi = ["psycopg2cffi"] -pymysql = ["pymysql", "pymysql (<1)"] +postgresql-psycopgbinary = ["psycopg[binary] (>=3.0.7)"] +pymysql = ["pymysql"] sqlcipher = ["sqlcipher3_binary"] -[[package]] -name = "sqlalchemy-redshift" -version = "0.8.14" -description = "Amazon Redshift Dialect for sqlalchemy" -optional = true -python-versions = ">=3.4" -files = [ - {file = "sqlalchemy-redshift-0.8.14.tar.gz", hash = "sha256:1f1f78d8ef7febaf0553d64fe247fc08acbfec84d8e1d2dc8264c656cc623622"}, - {file = "sqlalchemy_redshift-0.8.14-py2.py3-none-any.whl", hash = "sha256:cfdfae2c8fb3043c181e2baedd4ee425c1ca7efed20f3c5ae274838d1015f919"}, -] - -[package.dependencies] -packaging = "*" -SQLAlchemy = ">=0.9.2,<2.0.0" - [[package]] name = "stack-data" version = "0.6.3" @@ -6751,7 +6743,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "duckduckgo-search", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "ollama", "opensearch-py", "opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "qdrant-client", "redis", "snowflake-sqlalchemy", "sqlalchemy", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-cohere = ["cohere"] @@ -6775,15 +6767,15 @@ drivers-prompt-huggingface = ["huggingface-hub"] drivers-prompt-huggingface-pipeline = ["transformers"] drivers-prompt-ollama = ["ollama"] drivers-rerank-cohere = ["cohere"] -drivers-sql-postgres = ["pgvector", "psycopg2-binary"] -drivers-sql-redshift = ["boto3", "sqlalchemy-redshift"] -drivers-sql-snowflake = ["snowflake-sqlalchemy"] +drivers-sql-amazon-redshift = ["boto3"] +drivers-sql-postgres = ["pgvector", "psycopg2-binary", "sqlalchemy"] +drivers-sql-snowflake = ["snowflake-sqlalchemy", "sqlalchemy"] drivers-vector-amazon-opensearch = ["boto3", "opensearch-py"] drivers-vector-marqo = ["marqo"] drivers-vector-mongodb = ["pymongo"] drivers-vector-opensearch = ["opensearch-py"] drivers-vector-pinecone = ["pinecone-client"] -drivers-vector-postgresql = ["pgvector", "psycopg2-binary"] +drivers-vector-postgresql = ["pgvector", "psycopg2-binary", "sqlalchemy"] drivers-vector-qdrant = ["qdrant-client"] drivers-vector-redis = ["redis"] drivers-web-scraper-markdownify = ["beautifulsoup4", "markdownify", "playwright"] @@ -6794,8 +6786,9 @@ loaders-dataframe = ["pandas"] loaders-email = ["mail-parser"] loaders-image = ["pillow"] loaders-pdf = ["pypdf"] +loaders-sql = ["sqlalchemy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "9bd25bfc6e645b80acebb1266659832642799443b5f7314dc42487f4e67f1e42" +content-hash = "d3833e71fdc700bf0f2f6303c09a9ebccc55fe14ce712ee84e7b97a60f2da625" diff --git a/pyproject.toml b/pyproject.toml index 08b6ab618..68b99a716 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,6 @@ tenacity = ">=8.0" numpy = ">=1" stringcase = "^1.2.0" docker = "^7.1.0" -sqlalchemy = "~=1.0" requests = "^2.32.0" # drivers @@ -35,8 +34,7 @@ anthropic = { version = "^0.29.0", optional = true } transformers = { version = "^4.39.3", optional = true, extras=["torch"] } huggingface-hub = { version = ">=0.13", optional = true } boto3 = { version = "^1.34.119", optional = true } -sqlalchemy-redshift = { version = "*", optional = true } -snowflake-sqlalchemy = { version = "^1.4.7", optional = true } +snowflake-sqlalchemy = { version = "^1.6.1", optional = true } pinecone-client = { version = "^3", optional = true } pymongo = { version = "*", optional = true } marqo = { version = ">=1.1.0", optional = true } @@ -55,6 +53,7 @@ qdrant-client = { version = ">=1.9.1", optional = true } pusher = {version = "^3.3.2", optional = true} ollama = {version = "^0.2.1", optional = true} duckduckgo-search = {version = "^6.1.12", optional = true} +sqlalchemy = {version = "^2.0.31", optional = true} opentelemetry-sdk = {version = "^1.25.0", optional = true} opentelemetry-api = {version = "^1.25.0", optional = true} opentelemetry-instrumentation = {version = "^0.46b0", optional = true} @@ -78,9 +77,9 @@ drivers-prompt-amazon-sagemaker = ["boto3", "transformers"] drivers-prompt-google = ["google-generativeai"] drivers-prompt-ollama = ["ollama"] -drivers-sql-redshift = ["sqlalchemy-redshift", "boto3"] -drivers-sql-snowflake = ["snowflake-sqlalchemy", "snowflake", "snowflake-connector-python"] -drivers-sql-postgres = ["pgvector", "psycopg2-binary"] +drivers-sql-amazon-redshift = ["boto3"] +drivers-sql-snowflake = ["sqlalchemy", "snowflake-sqlalchemy", "snowflake"] +drivers-sql-postgres = ["sqlalchemy", "pgvector", "psycopg2-binary"] drivers-memory-conversation-amazon-dynamodb = ["boto3"] drivers-memory-conversation-redis = ["redis"] @@ -91,7 +90,7 @@ drivers-vector-mongodb = ["pymongo"] drivers-vector-redis = ["redis"] drivers-vector-opensearch = ["opensearch-py"] drivers-vector-amazon-opensearch = ["opensearch-py", "boto3"] -drivers-vector-postgresql = ["pgvector", "psycopg2-binary"] +drivers-vector-postgresql = ["sqlalchemy", "pgvector", "psycopg2-binary"] drivers-vector-qdrant = ["qdrant-client"] drivers-embedding-amazon-bedrock = ["boto3"] @@ -133,6 +132,7 @@ loaders-pdf = ["pypdf"] loaders-image = ["pillow"] loaders-email = ["mail-parser"] loaders-audio = ["filetype"] +loaders-sql = ["sqlalchemy"] all = [ # drivers @@ -140,7 +140,7 @@ all = [ "anthropic", "hugginface-hub", "transformers", - "sqlalchemy-redshift", + "sqlalchemy", "boto3", "snowflake-sqlalchemy", "snowflake", From 40959cd362ff6bb9676e2c2461a96370035d35b5 Mon Sep 17 00:00:00 2001 From: CJ Kindel Date: Thu, 18 Jul 2024 18:06:51 -0700 Subject: [PATCH 86/87] Datadog observability driver (#998) --- CHANGELOG.md | 1 + griptape/drivers/__init__.py | 2 ++ .../datadog_observability_driver.py | 22 +++++++++++++++ .../griptape_cloud_observability_driver.py | 3 -- .../open_telemetry_observability_driver.py | 14 ++++++++-- poetry.lock | 4 ++- pyproject.toml | 7 +++++ .../test_datadog_observability_driver.py | 28 +++++++++++++++++++ ...est_open_telemetry_observability_driver.py | 19 +++++++++++-- 9 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 griptape/drivers/observability/datadog_observability_driver.py create mode 100644 tests/unit/drivers/observability/test_datadog_observability_driver.py diff --git a/CHANGELOG.md b/CHANGELOG.md index b4b813a2b..bc364e035 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `DummyObservabilityDriver` as a no-op Observability Driver. - `OpenTelemetryObservabilityDriver` for sending observability data to an open telemetry collector or vendor. - `GriptapeCloudObservabilityDriver` for sending observability data to Griptape Cloud. +- `DatadogObservabilityDriver` for sending observability data to a Datadog Agent. - `Observability` context manager for enabling observability and configuring which Observability Driver to use. - `@observable` decorator for selecting which functions/methods to provide observability for. - `GenericArtifact` for storing any data. diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 8d84b68cf..4a516caf9 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -113,6 +113,7 @@ from .observability.no_op_observability_driver import NoOpObservabilityDriver from .observability.open_telemetry_observability_driver import OpenTelemetryObservabilityDriver from .observability.griptape_cloud_observability_driver import GriptapeCloudObservabilityDriver +from .observability.datadog_observability_driver import DatadogObservabilityDriver __all__ = [ "BasePromptDriver", @@ -211,4 +212,5 @@ "NoOpObservabilityDriver", "OpenTelemetryObservabilityDriver", "GriptapeCloudObservabilityDriver", + "DatadogObservabilityDriver", ] diff --git a/griptape/drivers/observability/datadog_observability_driver.py b/griptape/drivers/observability/datadog_observability_driver.py new file mode 100644 index 000000000..019fd76b6 --- /dev/null +++ b/griptape/drivers/observability/datadog_observability_driver.py @@ -0,0 +1,22 @@ +import os + +from attrs import Factory, define, field +from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter +from opentelemetry.sdk.trace import SpanProcessor +from opentelemetry.sdk.trace.export import BatchSpanProcessor + +from griptape.drivers.observability.open_telemetry_observability_driver import OpenTelemetryObservabilityDriver + + +@define +class DatadogObservabilityDriver(OpenTelemetryObservabilityDriver): + datadog_agent_endpoint: str = field( + default=Factory(lambda: os.getenv("DD_AGENT_ENDPOINT", "http://localhost:4318")), kw_only=True + ) + span_processor: SpanProcessor = field( + default=Factory( + lambda self: BatchSpanProcessor(OTLPSpanExporter(endpoint=f"{self.datadog_agent_endpoint}/v1/traces")), + takes_self=True, + ), + kw_only=True, + ) diff --git a/griptape/drivers/observability/griptape_cloud_observability_driver.py b/griptape/drivers/observability/griptape_cloud_observability_driver.py index e520def50..eec5f5f90 100644 --- a/griptape/drivers/observability/griptape_cloud_observability_driver.py +++ b/griptape/drivers/observability/griptape_cloud_observability_driver.py @@ -7,7 +7,6 @@ import requests from attrs import Attribute, Factory, define, field -from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter, SpanExportResult from opentelemetry.sdk.util import ns_to_iso_str from opentelemetry.trace import INVALID_SPAN, get_current_span @@ -57,7 +56,6 @@ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult: response = requests.post(url=url, json=payload, headers=self.headers) return SpanExportResult.SUCCESS if response.status_code == 200 else SpanExportResult.FAILURE - service_name: str = field(default="griptape-cloud", kw_only=True) base_url: str = field( default=Factory(lambda: os.getenv("GT_CLOUD_BASE_URL", "https://cloud.griptape.ai")), kw_only=True ) @@ -80,7 +78,6 @@ def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult: ), kw_only=True, ) - trace_provider: TracerProvider = field(default=Factory(lambda: TracerProvider()), kw_only=True) @structure_run_id.validator # pyright: ignore[reportAttributeAccessIssue] def validate_run_id(self, _: Attribute, structure_run_id: str) -> None: diff --git a/griptape/drivers/observability/open_telemetry_observability_driver.py b/griptape/drivers/observability/open_telemetry_observability_driver.py index fec067a4b..97a5633fb 100644 --- a/griptape/drivers/observability/open_telemetry_observability_driver.py +++ b/griptape/drivers/observability/open_telemetry_observability_driver.py @@ -18,11 +18,13 @@ @define class OpenTelemetryObservabilityDriver(BaseObservabilityDriver): - service_name: str = field(kw_only=True) + service_name: str = field(default="griptape", kw_only=True) span_processor: SpanProcessor = field(kw_only=True) + service_version: Optional[str] = field(default=None, kw_only=True) + deployment_env: Optional[str] = field(default=None, kw_only=True) trace_provider: TracerProvider = field( default=Factory( - lambda self: TracerProvider(resource=Resource(attributes={"service.name": self.service_name})), + lambda self: self._trace_provider_factory(), takes_self=True, ), kw_only=True, @@ -30,6 +32,14 @@ class OpenTelemetryObservabilityDriver(BaseObservabilityDriver): _tracer: Optional[Tracer] = None _root_span_context_manager: Any = None + def _trace_provider_factory(self) -> TracerProvider: + attributes = {"service.name": self.service_name} + if self.service_version is not None: + attributes["service.version"] = self.service_version + if self.deployment_env is not None: + attributes["deployment.environment"] = self.deployment_env + return TracerProvider(resource=Resource(attributes=attributes)) # pyright: ignore[reportArgumentType] + def __attrs_post_init__(self) -> None: self.trace_provider.add_span_processor(self.span_processor) self._tracer = get_tracer(self.service_name, tracer_provider=self.trace_provider) diff --git a/poetry.lock b/poetry.lock index 322b71d92..ca7b11bf2 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4868,6 +4868,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -6756,6 +6757,7 @@ drivers-event-listener-amazon-sqs = ["boto3"] drivers-event-listener-pusher = ["pusher"] drivers-memory-conversation-amazon-dynamodb = ["boto3"] drivers-memory-conversation-redis = ["redis"] +drivers-observability-datadog = ["opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk"] drivers-observability-griptape-cloud = ["opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk"] drivers-observability-opentelemetry = ["opentelemetry-api", "opentelemetry-exporter-otlp-proto-http", "opentelemetry-instrumentation", "opentelemetry-instrumentation-threading", "opentelemetry-sdk"] drivers-prompt-amazon-bedrock = ["anthropic", "boto3"] @@ -6791,4 +6793,4 @@ loaders-sql = ["sqlalchemy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "d3833e71fdc700bf0f2f6303c09a9ebccc55fe14ce712ee84e7b97a60f2da625" +content-hash = "a06adf2d65a6b68a9c4bdcbb7320a804f6bc78b4698e5ccffff8dd2620ee9678" diff --git a/pyproject.toml b/pyproject.toml index 68b99a716..04c1cdda6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -126,6 +126,13 @@ drivers-observability-griptape-cloud = [ "opentelemetry-instrumentation-threading", "opentelemetry-exporter-otlp-proto-http", ] +drivers-observability-datadog = [ + "opentelemetry-sdk", + "opentelemetry-api", + "opentelemetry-instrumentation", + "opentelemetry-instrumentation-threading", + "opentelemetry-exporter-otlp-proto-http", +] loaders-dataframe = ["pandas"] loaders-pdf = ["pypdf"] diff --git a/tests/unit/drivers/observability/test_datadog_observability_driver.py b/tests/unit/drivers/observability/test_datadog_observability_driver.py new file mode 100644 index 000000000..022c87248 --- /dev/null +++ b/tests/unit/drivers/observability/test_datadog_observability_driver.py @@ -0,0 +1,28 @@ +import os +from unittest import mock + +from griptape.drivers import DatadogObservabilityDriver + + +class TestDatadogTelemetryObservabilityDriver: + def test_init(self): + driver = DatadogObservabilityDriver() + + assert driver.service_name == "griptape" + assert driver.datadog_agent_endpoint == "http://localhost:4318" + + @mock.patch.dict(os.environ, {"DD_AGENT_ENDPOINT": "http://griptape.ai:1234"}) + def test_init_env_var_dd_agent(self): + driver = DatadogObservabilityDriver() + + assert driver.datadog_agent_endpoint == "http://griptape.ai:1234" + + def test_init_set_dd_agent(self): + driver = DatadogObservabilityDriver(datadog_agent_endpoint="http://griptape.ai:4321") + + assert driver.datadog_agent_endpoint == "http://griptape.ai:4321" + + def test_init_set_service_name(self): + driver = DatadogObservabilityDriver(service_name="test") + + assert driver.service_name == "test" diff --git a/tests/unit/drivers/observability/test_open_telemetry_observability_driver.py b/tests/unit/drivers/observability/test_open_telemetry_observability_driver.py index b903fb1c9..4f7ce50f0 100644 --- a/tests/unit/drivers/observability/test_open_telemetry_observability_driver.py +++ b/tests/unit/drivers/observability/test_open_telemetry_observability_driver.py @@ -23,10 +23,23 @@ def span_processor(self, mock_span_exporter): @pytest.fixture() def driver(self, span_processor): - return OpenTelemetryObservabilityDriver(service_name="test", span_processor=span_processor) + return OpenTelemetryObservabilityDriver(span_processor=span_processor) - def test_init(self, span_processor): - OpenTelemetryObservabilityDriver(service_name="test", span_processor=span_processor) + def test_init_no_optional(self, span_processor): + driver = OpenTelemetryObservabilityDriver(span_processor=span_processor) + + assert driver.service_name == "griptape" + assert driver.service_version is None + assert driver.deployment_env is None + + def test_init_all_optional(self, span_processor): + driver = OpenTelemetryObservabilityDriver( + service_name="griptape", service_version="1.0", deployment_env="test", span_processor=span_processor + ) + + assert driver.service_name == "griptape" + assert driver.service_version == "1.0" + assert driver.deployment_env == "test" def test_context_manager_pass(self, driver, mock_span_exporter): expected_spans = ExpectedSpans(spans=[ExpectedSpan(name="main", parent=None, status_code=StatusCode.OK)]) From 384c78f5641b32754e62fc7bc2775fc36bfa4de0 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Fri, 19 Jul 2024 06:20:40 -0700 Subject: [PATCH 87/87] Update marqo dependency (#1001) --- CHANGELOG.md | 1 + poetry.lock | 189 +++++++++++++++++++++++++++++++++++-------------- pyproject.toml | 2 +- 3 files changed, 137 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc364e035..e7d2f757a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **BREAKING**: Make `sqlalchemy` an optional dependency. - **BREAKING**: Rename `drivers-sql-redshift` to `drivers-sql-amazon-redshift` - Removed unnecessary `sqlalchemy-redshift` dependency in `drivers-sql-amazon-redshift` extra. +- **BREAKING**: Update `marqo` dependency to `^3.7.0`. - Removed unnecessary `transformers` dependency in `drivers-prompt-huggingface` extra. - Removed unnecessary `huggingface-hub` dependency in `drivers-prompt-huggingface-pipeline` extra. diff --git a/poetry.lock b/poetry.lock index ca7b11bf2..0cd52214d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -152,6 +152,17 @@ files = [ [package.dependencies] frozenlist = ">=1.1.0" +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + [[package]] name = "anthropic" version = "0.29.0" @@ -2707,18 +2718,18 @@ files = [ [[package]] name = "marqo" -version = "3.4.0" +version = "3.7.0" description = "Tensor search for humans" optional = true python-versions = ">=3" files = [ - {file = "marqo-3.4.0-py3-none-any.whl", hash = "sha256:4b1b70f841596f6ae13bab61646286b0a1b5792e0e31815f757c15286fef0570"}, - {file = "marqo-3.4.0.tar.gz", hash = "sha256:d1a0ccc8b938c456e8ed56c2326bcff2b7a4d039496a24394b29d67dafb61b64"}, + {file = "marqo-3.7.0-py3-none-any.whl", hash = "sha256:6f1ff86c3faadb31415bd1adf3e805b2927588c1a5756eeea8fb63097bf94c8a"}, + {file = "marqo-3.7.0.tar.gz", hash = "sha256:d144cf69a41932fc664f04fc994b8c050998bd730b988e1d3fbe6bd20d9c820e"}, ] [package.dependencies] packaging = "*" -pydantic = "<2.0.0" +pydantic = ">=2.0.0" requests = "*" typing-extensions = ">=4.5.0" urllib3 = ">=1.26.0,<2.0.0" @@ -4320,55 +4331,126 @@ files = [ [[package]] name = "pydantic" -version = "1.10.16" -description = "Data validation and settings management using python type hints" +version = "2.8.2" +description = "Data validation using Python type hints" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic-1.10.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1a539ac40551b01a85e899829aa43ca8036707474af8d74b48be288d4d2d2846"}, - {file = "pydantic-1.10.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8a4fcc7b0b8038dbda2dda642cff024032dfae24a7960cc58e57a39eb1949b9b"}, - {file = "pydantic-1.10.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4660dd697de1ae2d4305a85161312611f64d5360663a9ba026cd6ad9e3fe14c3"}, - {file = "pydantic-1.10.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:900a787c574f903a97d0bf52a43ff3b6cf4fa0119674bcfc0e5fd1056d388ad9"}, - {file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:d30192a63e6d3334c3f0c0506dd6ae9f1dce7b2f8845518915291393a5707a22"}, - {file = "pydantic-1.10.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:16cf23ed599ca5ca937e37ba50ab114e6b5c387eb43a6cc533701605ad1be611"}, - {file = "pydantic-1.10.16-cp310-cp310-win_amd64.whl", hash = "sha256:8d23111f41d1e19334edd51438fd57933f3eee7d9d2fa8cc3f5eda515a272055"}, - {file = "pydantic-1.10.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ef287b8d7fc0e86a8bd1f902c61aff6ba9479c50563242fe88ba39692e98e1e0"}, - {file = "pydantic-1.10.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b9ded699bfd3b3912d796ff388b0c607e6d35d41053d37aaf8fd6082c660de9a"}, - {file = "pydantic-1.10.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:daeb199814333e4426c5e86d7fb610f4e230289f28cab90eb4de27330bef93cf"}, - {file = "pydantic-1.10.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5973843f1fa99ec6c3ac8d1a8698ac9340b35e45cca6c3e5beb5c3bd1ef15de6"}, - {file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6b8a7788a8528a558828fe4a48783cafdcf2612d13c491594a8161dc721629c"}, - {file = "pydantic-1.10.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8abaecf54dacc9d991dda93c3b880d41092a8924cde94eeb811d7d9ab55df7d8"}, - {file = "pydantic-1.10.16-cp311-cp311-win_amd64.whl", hash = "sha256:ddc7b682fbd23f051edc419dc6977e11dd2dbdd0cef9d05f0e15d1387862d230"}, - {file = "pydantic-1.10.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:067c2b5539f7839653ad8c3d1fc2f1343338da8677b7b2172abf3cd3fdc8f719"}, - {file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d1fc943583c046ecad0ff5d6281ee571b64e11b5503d9595febdce54f38b290"}, - {file = "pydantic-1.10.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18548b30ccebe71d380b0886cc44ea5d80afbcc155e3518792f13677ad06097d"}, - {file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4e92292f9580fc5ea517618580fac24e9f6dc5657196e977c194a8e50e14f5a9"}, - {file = "pydantic-1.10.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5da8bc4bb4f85b8c97cc7f11141fddbbd29eb25e843672e5807e19cc3d7c1b7f"}, - {file = "pydantic-1.10.16-cp37-cp37m-win_amd64.whl", hash = "sha256:a04ee1ea34172b87707a6ecfcdb120d7656892206b7c4dbdb771a73e90179fcb"}, - {file = "pydantic-1.10.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4fa86469fd46e732242c7acb83282d33f83591a7e06f840481327d5bf6d96112"}, - {file = "pydantic-1.10.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:89c2783dc261726fe7a5ce1121bce29a2f7eb9b1e704c68df2b117604e3b346f"}, - {file = "pydantic-1.10.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78e59fa919fa7a192f423d190d8660c35dd444efa9216662273f36826765424b"}, - {file = "pydantic-1.10.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b7e82a80068c77f4b074032e031e642530b6d45cb8121fc7c99faa31fb6c6b72"}, - {file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d82d5956cee27a30e26a5b88d00a6a2a15a4855e13c9baf50175976de0dc282c"}, - {file = "pydantic-1.10.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b7b99424cc0970ff08deccb549b5a6ec1040c0b449eab91723e64df2bd8fdca"}, - {file = "pydantic-1.10.16-cp38-cp38-win_amd64.whl", hash = "sha256:d97a35e1ba59442775201657171f601a2879e63517a55862a51f8d67cdfc0017"}, - {file = "pydantic-1.10.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9d91f6866fd3e303c632207813ef6bc4d86055e21c5e5a0a311983a9ac5f0192"}, - {file = "pydantic-1.10.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d8d3c71d14c8bd26d2350c081908dbf59d5a6a8f9596d9ef2b09cc1e61c8662b"}, - {file = "pydantic-1.10.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b73e6386b439b4881d79244e9fc1e32d1e31e8d784673f5d58a000550c94a6c0"}, - {file = "pydantic-1.10.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f039881fb2ef86f6de6eacce6e71701b47500355738367413ccc1550b2a69cf"}, - {file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:3895ddb26f22bdddee7e49741486aa7b389258c6f6771943e87fc00eabd79134"}, - {file = "pydantic-1.10.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55b945da2756b5cef93d792521ad0d457fdf2f69fd5a2d10a27513f5281717dd"}, - {file = "pydantic-1.10.16-cp39-cp39-win_amd64.whl", hash = "sha256:22dd265c77c3976a34be78409b128cb84629284dfd1b69d2fa1507a36f84dc8b"}, - {file = "pydantic-1.10.16-py3-none-any.whl", hash = "sha256:aa2774ba5412fd1c5cb890d08e8b0a3bb5765898913ba1f61a65a4810f03cf29"}, - {file = "pydantic-1.10.16.tar.gz", hash = "sha256:8bb388f6244809af69ee384900b10b677a69f1980fdc655ea419710cffcb5610"}, -] - -[package.dependencies] -typing-extensions = ">=4.2.0" + {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, + {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, +] + +[package.dependencies] +annotated-types = ">=0.4.0" +pydantic-core = "2.20.1" +typing-extensions = [ + {version = ">=4.6.1", markers = "python_version < \"3.13\""}, + {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, +] [package.extras] -dotenv = ["python-dotenv (>=0.10.4)"] -email = ["email-validator (>=1.0.3)"] +email = ["email-validator (>=2.0.0)"] + +[[package]] +name = "pydantic-core" +version = "2.20.1" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, + {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, + {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, + {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, + {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, + {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, + {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, + {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, + {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, + {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, + {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, + {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, + {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, + {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, + {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, + {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, + {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, + {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, + {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, + {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, + {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, + {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, + {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, + {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, + {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, + {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, + {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, + {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, + {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, + {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, + {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, + {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, + {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, + {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, + {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pyee" @@ -4868,7 +4950,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -6264,13 +6345,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.11.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] @@ -6793,4 +6874,4 @@ loaders-sql = ["sqlalchemy"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a06adf2d65a6b68a9c4bdcbb7320a804f6bc78b4698e5ccffff8dd2620ee9678" +content-hash = "c3078839442b9b1546e2d90b6bbf5a70cdcb3ba92f6384685c17615171fd4cc0" diff --git a/pyproject.toml b/pyproject.toml index 04c1cdda6..12fc49199 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ boto3 = { version = "^1.34.119", optional = true } snowflake-sqlalchemy = { version = "^1.6.1", optional = true } pinecone-client = { version = "^3", optional = true } pymongo = { version = "*", optional = true } -marqo = { version = ">=1.1.0", optional = true } +marqo = { version = "^3.7.0", optional = true } redis = { version = "^4.6.0", optional = true } opensearch-py = { version = "^2.3.1", optional = true } pgvector = { version = "^0.2.3", optional = true }
  • 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

    |K@U0*Qigm>SUy(&x?Aee zD8JeJ+&|f+Pf_Dg+vkte&(I~NH=F&>Q2>%Cd|eV%_={Lwk+f!gRo&!P3Gh%9{{D!# z^!+X_YmOletTc3JLdospOAX}vP-BNjvM~gtz|KphjThzbJsnuK9JfPBRr*BhGtonG z9_kwB6)-@A$z{9PiO_etE)Nqht*Psr@c~dyu3_K#WQ{eHl`}L=>-x5PbDf!X&O$!C zZr08n3bEBh%&0kGKdUNN^|HRhxB&Dwgobh~AZ6hdsFAG*h0XC> zdXO(K%*mZ4*%#tY4@4&MP8zLQfHwB1_O*53-(ER%-rd!Fa|uuS8BfL=BTuU|PiMP| zsu&1{?!t9?djdn!tsuMA+rxr@CV1a;;My32YX~bB{j@l)svh+hveF0GlZX&+nMK7~8AZ(J8~ zQ0b_ghjUqR{Sv@y~^>jiDqSy)&fe z5u6l)1hodpNOg>}{rwjZl9$=H_2*JtWK|)LMJGo{ei5vHyYnnP~ zeghgGe8aQ;OaKFU+SRWxe2P{E$trMz&diIhffI3pjS)ju!5xeLbWE90lhzAwPC|zqd7VJ_l zjz%@^%>B8<|0VK0V1;s=%URMwmK%vkE|*?A+RhH(Ne_3pn^(sxy60T*q?b%IVXBq3 zm&eO8be&2VU)=QC-V3o%aV@k2=bS(rbC-Wh0m5FjpDXOYyd6%>#L*kYCLl#q<$T{G zA?sI$A1D;5G*}W#5KIs4)5QJ46e(bj*}6Ff+}D0JXliLT5zLMp5zyTmu??;Eh&NbK zCd5^W?1n4 z0N2Bs#`xeHf@==ojRO(aPk9(fh>MvAwqY|s>8tW-kBlWQPvEnm{DOR`gWrjhbx!%R zt!)$+<%!c%B1RX8r!8ew+fHGl(qN2045d~IcnwFx_v zJBZUPc*>90xi!De58;N9Wjd4*k7&z2v?x?dFBSW*-;|EM{;3=`rrwpctOjRp+O~LD z&PDb6zE}W`qyz40!QCG~Mh&iJQ|_l**75{k;wxT%S1mi%rQp*}fY;c#^T@2fURf5eoky zP{~Ivxp)(qKb4_j!gO3WcKvNQ!4ZCuFE<9CA~}vthAWVw>c;!cW|-z_WRs*&u9%3` z68neo2KA(X-Su887X3LviDNcGQ6ru}EFI}_Up9&p-1>DqpwGAf2GU2_rdYY1biG3YA-dOfo;)+K=gVVNNs98=Y_6&SbwZ}O)jyDN{-sgDS zvb&sUNtW{6r&Amck7ku<^%McWU)GzOZdu3PPOR#l7G&O}$TRxHt!BNzqbrl0Bz4(B z#x48{cXB{FSCwbN$aJo80i=3{R)eH)XfiLgosTY!9}&g zwTjG{wH*zz!+y*Q$ZDdemI2lc@t{O?m!qxpsBbM#hBw z3;k(V>zz?7_s7aKKqqT|j7q_OoR+FvaaVVLcQ$q@GFse4MqQBv9E`l}K@MngU#sc8 zbSgL7HpB$(e4Lg~ocCxghS#xBr8L8-;WK^sBmeCRH@c zW3Z0W;8@qlW9#^3@93eBy?=ISj9%)Vc8?z8Zg$IlLA~g78ve{Enc|>zMVfXTUr&+8 z-oBr37bZq_)Dy_DFncVD4)|hR{N}^Y&KES85!X?;kVGEDyN*bMfqH<%~KL)r?1^C#22LE<9V3!A# zo9zNgY$HAD6i(+=g5}|j8MV*7gI3=P2E!SS!(d=ey-?#W*C^gd;BY`eFwgnPr700biz2l9BSJUQP1W+y zym#*qkF1LQ#6m|Xkg67s)?s3dJ=Vyikh#L5(tD%Ne-+akNC0s>sCByJXEB2@%CvBR zRG3@Ky$g^cY|=B0o6neD6qsR3j<Ww_wZtwqB+U)KTe9md=oCkG6-cXJDQAQOs( z;9-ll3>oE55w`Wlp11akpd?pU>yzMgAPX%wmJa$L@vR*{ro_2G<`vy`fyMEGgNN8u zsjgm^v&$-Z&L45zKs_3xSt(Vz-wY9uOAcZrM>!{TD$6COb=Nj>@7Rr%JM`*u)i zbJT3n2O%xG+pkF#@U3-VQ`k=a#ao>;8Y{@}m*jrexSosE$xYLma$9j!YO;I< z5(fSlL=EnC^Pt2tUxWo9qp#55V{RquP^J*#wd~dvt+vdCepqTi67@|u!FSe$sKgW0 zonGEfALLQM=Xb`h8xED&?V3Wb;uzN+GfKmo0IISDYs5wqLWkNb`UYmw(FAD zlwj~BIb{frKsOw-k+o4?^5LS+V2ZBZVAu6`Xfh_bw%bYQ>0X-?fPI~TV(~RU?{O*b zeBLZV-di{{pv2ouvh%Cvo%zI$T@@Z$O?#_5?O0aB|6h%<(7vt)-6s*vR-llM+*y&S zC(wb`*eP`uxp5b)9T_!bH|zeMlsJyflOU?XzY-Pjgf)vTR=m_oBMkR}+O=Hm>g0s5 zw!erLBivtr$=!5$))R2Da49r&Z9~5BU_QSHKvR&Xg=-(CsnAgWvzwWwocZf-f%JNP zdrBT`gaIxH=YOS?zfQNAT!2bGdbVi`vt1o)(M0a4Xs5zhZoSwj%CZEu(s!}aHe}kf z*mP7gdf>;8TmSIkZ7VOoQK_|o5o0{DEGCU)SFDW;J82s(fWetr&k*=6xxpJV6!_kv z4$*ene&NNZD8?csOusilue0ZC#fk86a|6E1Zp$L;AMUao6fVW*6*UYfI(!r<5)fzy;@|7sh_6D`!lPe{$4xtHF5 zASc2O{{%xI_aKnKn&yU80;I}b2-8r9W2AFG2Jd5-uW1`WCAmU-!dC-p9MwvjYOfa{ zG5}axD#ec1s~f%?>CPkiXL4N7Ql!K`p=0!6st2c!v-kgW5OY#n@o&x_s9si;4Quu! zt7Lxubkr??6X|j86)}Iyp{FV$%8pelNN@aCIoAIQV88FgEDvLAvT|zp6jFLE1^q+4 z(|tu2LPTRhGO9X=fuTpERyPj#i;!~a+=_CH?f*y?w^kT{;C^J^WJj)E4J}K_Xb~Il z<@@%ExdF^k9r_S^VY9{KD=CeojZDaNhm&m#`|Qrcc<^U^_C#gE60K{EX)XDljMX~B zSRpYUGfovbbc$kw)(IhCAmoRR~wEEpK z>`bo24rr=pHd!SzgdkQOr-WC{VVp2v=7ld4`NMEyYlR-??=*R3c+qv^rF?tGHwPwVKw#gaHAU@s?OO6u8m+ z+(RKv=Q7LueV48^f7*~mkk-Goka?YvDK@cZm3eAiTQc7^dDjeR$opm#!I7@);Uj}~ z@Be#QX~4@g^lcI7w}G66hYeR~Q1COsC9@=vgj+$vVqscpo={{Xo#Q!2(8hZ)I-y`| z06;MDg5FV${%UjFO+J&1FhnddiER8gy@vNaAA+vri34Wlzi=@6ZQk{r6L2anMmW(| zP~z96%E#|@?<|lxLCW5Jy1{SV!+^p*Yl3H0uX_3!1fSY_tiA<`2cJ~RPJ=~(!n0^Q zQh^bbS+N5*_VnIS2M13<8FXm7^RtKhs-L5X9 z9OKf5C^L%%J=%X(hhSlM8fX?A7L)M?&_cP(ZEJ?VABs>`nO&%iUX?N4xE8507!o)LORCXaar|dhR_4|_o=>xoGZG1ogDs_09kvptQA-* zh>sQ-<{PjKntSk<8ZYw`&-07#CY;I-GIT`R$s=aZ&Rd2H;sk673Fm~Z z@w_$xIr!^57J&S6eK!pszy5Y@ z8-@beZL=m&QPf5@I}Uk$jlTSt)y$oT#$fGYLKmm6yL$>txC>oO{>iz@vK0aUt?iig z=p5Fc8+w1$hV6;v${^6F6lz2zu*}zZh^}daXxZn$(2w(t5eA!8fV=>m;ohU!bVF{B zpNehx^8x~O?PXa<%+ZW0X!4*I97xkzB#xOADkQ-@d7+?C;j@5uZz(i^n^@^66`~TJ zim~_haTjP=qpLKImp%zO@kVz}&m+UEK}=552q!SXd+pJk4){FB#ez)Zceo|Qv;PtS zXX^ZMN=2}>dHqO#9O2TdR)18qFPoy~`w*j*ghGohl2CYg))s21~;= zst8&C%E7&I!TyAI;#XZJ4o*4ys=N5cGmeO+%4JiVE+DeJO`&VoSr4M>)KDrCLiy#C zx)1w>HNbYm6#%9_+6ptsJ)xYbPGrCAn+jF1v2&Am_M!y6>@aY|=G;R6ASy8+%I$mB zJFkC9_nr?&q>jrye-J9ys=!cOB#qHA67RV@obdG@aSjl4^`W-q{dx>n~+8k zeE<>$`n9$#w^Wpk7 z6|YS7LrszXsfVO3jb(OU6T98_Nd-+fPM16e}q^}{)r~2 z-EEJWoT=7%>El(nPw^X-de^l!ay6V^=Dg$;*y7g@5sx{#Z^$%)2iAhQdtE`znE}R5 zI6QrTtrA58Ghu){7zj=DmZu%Cwps;(-jBb-Li=FR`SG!Uk_S5l*i%Z*wSnVD!mu7+ zq52JAwynKY>&uO%I78k@H6(K+Djd>OulLy=g-&jZgwrl;JdnEuL z)8bzq%qg;1!PZ6T+~jDAYQuIQK9uVO{ZFVoXdH(b^}t~1E_S=%HCwQ9`WW}mPq4fonVzY17B?Ks zD%82bI%D@``d@V614Lsp`fkbL-lIkc7_^k34ORfl>6vUzkdGM}VW!hn zSi><#yVl>>-I~u%tYi4`E`A-4p)e8Pw=s0IMa{&ij#6DDbVWgh1I-3kEc4d|e-Hum zKh~M#Kw{N~rdg=BD{CIDm_Ksf#e~@VoZMLJK zw6zp4Crp#Ty+Z%*v`K8KM317bTXFf$q}(4FoKjGbIa`0^g2~m<@BW&b{0Wcvl$X7j zZL4g*vu%u3{VL~7Zc)q9opk1i3Yc;0)G6wZkxHrzqsU5rL!bNGYZiFCmbQ>hVR63P z`|`1(tW6m#inwgVQ6+Nb!BRO^8Qb>@24@T-YX~2RcaKeFdq56E_KVTA&p)1Z6jI>^ z!V(&N2zo~@1vd7S@*b{oAHJF+0^s<@q!{W&BQL}bV}kiB^+n?`0ZgiOwJh375u%_D zFX8xWKe|~Lbe)D*WKv5GicW38a zlJWmEYwMM__zZP8_4S=9_l?Sib7-3%t*wzh>Dx-Al*_7|o9_6~)v{xtNlWR5|Wmp7s5;VI7VSRzR`-wYckh*t(2AP|a|f z0S%f_0>wctb*y12TH^c(m#)Ne%tVY?Qmk&4^$^HK zL$Sf@ePp2fDo=s8KKpGM@3*054=XvrIqhiFDH$=enxXKjoX?R50W{&eL5uFS?$v4SD+!M?!Q4 z3tA|}1eFqQxnOKk$_=*TjN;?pNfB&*KSVIaQwp&f@SbJ|sR0aqaR;@tHgs31y6ON{ zb;H3*c-xa}SON$z_1N%9Sd(@N)Gapc#3hYb*|9Sj(Pnq*)g$}l%NG#RLKKTMB+Sh& zsC8aX2Bm(c(NOSZGk0M4DF*N()coi$_r@TEB%BW)J6L1sLrij+ zqSqc%*6`Z#L=&DLr@bfOcS(EA(SJJfe2HK6QNeL`){V=D6QqZj*6j_{He{^ii(t&5{^tQiY%f?45maiULYJRO=M#3~x|cnm z+GcXPTQPqD8g*tX^+xhj?sP$1#6m-wL#h<W{7x>jRdQ2 z>mBwg?CAp<-T_@1-v5VH6YWXAEpHb;v_^8o{9rk&H=&@A+?t!?pc;aF_3x2*?a#c` zjV3G3n%WtUIvwm?xH-LDPF4!_8iJD&a8e2}TEkZ*bE(!c>~6wcJu&|{6`|sXqPb=A z*4A)&Mj&p~fpgocsxLcViFR;WsD;4_G+F;SC0$}-q}WaQv}lLzEqBIHLEs}JN{CG^ zHFA(Acq}*)7MPUsCanI3>NNi#hLx(`PYu}Up0}1hFow^7C{GHThVD?;*Z|V@Jx-tw z`u|tQFjYAb%EMQgrsQPKk1gwc?Wr%x%BUb8dTjufw&Ulq%pHXqI1(m0;Z0qD-8A?LwEIGAyKi1avgf9FK92I9<3ZbE71mVTm9C0 z`~xlgzE~6>Aq|2*GVbnEej=sHOu)=-KY1^dm8x`KFNsyF705kAMeS^jxW>a0&3$XJ zYJpP@l;4V*2o<8ySfTc&{Ej;1>dZPllj>#1&JUL2fD|8yN004fCC`_0F>3!FB$er1 z-bDX=*Kb?I|LKQHLx66!uw512xdR$v%;gAVFFJIH{?-2@#pFP5p2NJGdE&COkMBd4 zB;muW4q3Ic8p}xHPY8LX^pc|i~3H7N)+9WOK&CmKu`7} z>ZQO9Ue-v}rONHK8W*^C*|UjP$lO*8i5CrX%+ zBZXeJHF??b^>eBkOJqG$1=FboFIPb%nux$xkDl6y}Srw09sdVH-{7?%@{T zr7KL{@FF96uIMyy{L*SV56bU4&OUE>a0K3Cdz6xC+G2N3hLJl2E-n}})Fo#^S5M%zDVE`Xxrt{em4;^Ww5NT3*I^ zeb(=f5;RW>u$TUcaS5IrP6OTa#c|6vbGSDK3hp*4FLA5UNvc=Q%rH$vNZNZi)QV#d zFrrT@-Tc^A49G{Y;XHRXhihaQ28cZO1Cwef96qC@el9G;a)W@k6Z7PXiW8bNS%`Uy zgn+mb1~08$2*EUq5sJz5DJ>t;&MULbUcm9MgCu7>yxb3_B>$Djta<6JPe}td2y^c$ zLhuM>CMS5PXc*Um;?6Yl>&m*L&5rUWBZaqRkL^FkmJprC92zx?qpQ*`hkH$=eFsWG2{P)n&`!k3>OEG}?bm|0~> zBm!3`J<41Ed;4Y}=+(c$GeairI_3mdds5rKV29=-iVI(u=Gv<>stoD%gSV!@pvPgs z8iSe{>$aTV9kO77!kDjZLCg#ZvpwE)_XHFM!~^F*!W=)i?o$~$3>jUb(ET%7_K(?` z>!+4oo%gDpGI`L`yidw7RO#74*P-SMWtwwlXiUB^(035c$i;2!N5J-?njM=r*GWfr znyKxLT!{woUxO0|Pcc4g+XDfn(UAiru}sbUD|)8JJ?(ZW{R7d>qM@A@v+pgnv`JN{ znZzvTN$Mvvf(R3gAx5!SS*U^pSDnj}(KH$FG}P{}k}S7T?w2Y)_AEMFLfCE{H z1qSG4E?y5%J59EIzHYlG`^52J`tRFF5civltDJ-AssAs8Z|eeTMvA7#Y2N+s{s? zkMd(nd_DVZ3&ddkl{LeGO|hFa!PA~2ZJp3zZjK!%=diRW-&D^IgS3n3K8N#BL2yY3 zno&u#XahxW+o$}KWd1tJNjxk7DF~$?G#dZv?LQV0V(_tACEWK#ttRvD-MfDi@KMh8*pdOmZV~2H^x>(YEO)7J^(EXd1Q#zPm2V$fPVV%4qG8g7X zJ8)In!A1Dv@o{JYhvnbIyFdl13?R_+KyM91=Ss^+G5~G}Ayu?Q-kEm+#CS`^j2C5s zf8bee(5;V~^THUy7X-O>Z?3XzFZ5|0RI7BdX~M<%93GE3ci}kb&gKN3^7T8c)1#0~ zOP~W-i0xT&<&*Ik=omZl7?)s$_P^Bgvq3egvLW~VBctM^S|OlcRpQKKWEZCq)bun2 z_+{*lb^Llvx^~7C{!%+ObjoWg9Q^2pHgp810&S-Qu`$4A%+KP+FR2~v(+}c}uESx_ zu5gna2jPFn*7P*c^m=We@Zyc5a!}b|!czs(S{yTEJ6jR}5-Td-N&3~%-s=u5S`s$t#*1{*7}Uco*#$sgEEi^tv1towr9jw-JK;m6kuMF>U^3>oW6VsHoV6KnES zOvpvrr$#BkLEpp{*o4Si@5Z3Jt0VSuEG!a7VYBo1Ex2Ka(C?n6p|AecL%5)*t^*cE zOyV`kYfPE4KO_fu{lpl)^tAi0N$%sKZ^tdW*J@pGEz%Hcdm=;m=Tx>PS+*u$A!t~x zN4#Q6)ILX%hp0hf_YD7Y#b>19zno8b_`K5lgCpXKYV^XqI9@5Zi!$pM^ zw_2!!^V3#R`A;Gi9BmVOt5~znfdkVd0y1#Mr812zHjX~P zYUmbgSt{|orx>v1;4q&gfDL-1WvdO+M7s!FUSbL*rhM9<&fD+hT8y#l~2^K-IpvU{l6lS$vIxxrw-a`Zc+LF81 zw~-SLuQyA~N;NT;Yrl)jwbUWP^JkpbkK*#Dtp2ESj*r}bAcx> zR5Ge{&|U_2=z)%~CU=h(#+vreli}EVf)68jXE_xWOiA2)wx!%x)I{uhx1QO)6SVUh z|Kp-NtDk55v2R;2ka?5Zog7r|EKn0hRT)nJryB~0ka-8b{2y} zifk*yYSuacdlk-IgmY|eoLVn4iO5k6V%3J2fS}z04C8U>doX^`EDVbzu}$=kdJftz zJUt?*|G#xXSN$Fb=58eopI&(7dHwa;sSguTua1_dxs|>TE-2wnFVyT61J-pVyP!-= zIK&Ykd5UPaOc9mC65~Q_Zk6lOIHZv9Kq0i0qGSH5uDhRkxWTG8*}0n3{*+afo-SU> zLE+MHXux*{vQ%T?TJwM1jC%{Lh~fu1o!8USSBF?jk>~ zVSoluD6*6&ZIdu6s4}LDh32P)IFpSOglsjypGEqa z^Cl}*6*d7hC=s31PnlKbImULjM0^Io9nx`ZtAukTkJG#kT7(Cy5_Dw&O;7*?_= zAJb2%2{-U3!PTB<VpBcF(s+5@4$TXk5+f>wm*dKK~FDp;q#EWV;_rz@N zv)db$J#O(;Sk?IhzAuU#5iauT7BM4}O|ISrCM?YpZW)Q((X9{1Xd0Ij19?i{d05IMSW8RAn9*m29-Ed?m0HcU6lN zdKTG8HqKBdYlxrd^P;v%ITtX%4^Wc%*zvF8d90K0!$a8so^&cHT?husqiTD*Y zo;5JjO0&LWGn*`TW)h%G7L>7_{kh3*(1Wg+LP*8PbNA|w<-ybTt~^{VDMko{VAl2* zG~I~C5;5p{+B1R7tLcWA*Lg7@f7>ja*CrEUQ-v)pO;VTGuv_2*?N7V%sSFEFw1T!v z$mbv6gfYNgtQ_4tq7=b@baOp_Dk&ZD!eOS_-w8WE-k$|ulpb}-!DyA2d!}&hw=-@* z&>4TFHix+!esLZfIwouD@}B!bPpQoY8m#!tkapF;e|PV!6Lv`V8&pW_m65D`o}F71 zdEG)o(Xz3@8Z?Ml8cx2nX52r6o*K3eqfvBv5EnT}X@t@UgU4)@=pDe)(YXxmaT|F8 zA{8cire8`p5xXm}y`e~JGQUkRQqA#&p!jCoA|J-0vHP1f%#V;-SZoGzz|?8d{;+v# ziceE7x++FAP5G*f5q_9n4#C;sJUrMrl@P0bjtG=Kp37Gh53G4QeNz=qsm_(*AJ8CB zEPVyIx7~^{1-z6nhx22|59wSnOoMO%h}rGa=;RX&t2|dCG#Yxk**coQzD>lf*szP{ zCsBvvR0YU2Lz_{BcjfBQNN}3uH2oE9rhbC04EcU z79s)TJn@+X9lA6woyCq&THjuaz!&tWe|hlUMI*adJQoe4os$&rfF1}M!6mRD&ekM? zpTFpn!_Vl-mfZbodP#Lhm)S531ew;xu5sW7>*Q`c2w+w(CEHshC`X6m>6uC1*_=Jr z;3tRV<)jEYJo&eceZf$8I340KQ$BFx)0OWJ)8YN*#qwrt*kv(P4d}O5*u;z|mdB@1 zT*BeA?&!~p%qMsJjbK6XpW*z%N&$brOr** z^IB&>M?eFK8M&~%fHuWEBI#|=|0>leDAqi&v}x?ddMqAlSttZ}bR4lL8%pUCMD(%A zchAGm1=fWd@5cNkv;b1(9dzuQ+cXs;jIDG~6O6mhmlf5C6D*xp{JZ={G!gK*6pB!C zU*RzfC_q%}z;!qGZ|DMA#yLJ2BF6#+Aa8~wok>pJRi2TE=%H^uLC$jrBfKx$PP;w! zm*W|kBq7o1u=Y0Qt03>n%-z~B5L}Zq?%Nji?_RV^y#3`2$2#(L!B}#NVZLDM0{X*d zyn)q<0h_v&Cnl>;T#>V=frC~Nv|jjcFDhdvz}rqbjHJd)S0cv~_W!=D)GuAcC9Q4$ zS1+|1R4Ktx=(kr$F!fS%z{JH@G5PtSfRqql5C7OKd(#;SB`pll`O?}LLS&%n6NIA7 zLWZ-0^N;hd4t;6P@M#oj*~(iNL9BN zjP3KU6tSR3lxZ=XhpHSuCq8D7G6A{kO)Ow2kGc&kpD*G7C|GKZ=@i)L6qh_an#vfO z9XsgN+#~kUuufK@8d~pteHMer}q}Lfu&ehYkKu;;M(krou zK15FA27`2u`K2;G;r_hv(?JZ~kj2s!RgSE>WfQkb)%5RBH)_IgGzAzs+2kEEtkhhB zw$D^$yWi!iP{3-Veb#BG(C6K+2LXMl`J7>P0y*KA=5t81z5o1+DQ-b0H4 zDn}jwbGjUS5H7MZcdYPW>HiL zFXsEvgV}@{8Icp=IuGK;Au~5?_STj+vGz=w6qr(O@!sdgveVvmKqNYjC}goN>%j}f z=+EMz&#KQ%xa)X4Osl|p$EKG6-_uEeQZ2bsTM{Z)Y4ATO)Y(Do zha)BDT(9R*9r#Ajlzt|JaFuHjAQdYTn446r)8j94i0A!ar74Wg)M$hcqxl-*sm)<8 zxm%Rg@s2uWYwm_o&k`Qt)e_=G8gOiXjL#$edIvArybfNlsQV_kc5NVuW8)=t&1Rgt zzyf6OFR%Y+%l4}==W&*#573dAs(8&65ETF>|6*2{s?n$^QCHwP3C17%vslDDKp)hj zOOrg={GV{`-A^0-;{rb7S<@42x%9~umh{h1GBH@9k=K*(SIT+Nc&Q&q!aG2;YVQNw zC@|va3^^wL#XCka5tVaWO4ZkOS8r=j}Q0(RV4F1?6e91#8yG`jOa7$7o5|K>4!dW6MSaXudG>R*z z+l12RVsy$wr)%dKlBp;kYgIrbktj?^*d@D@a)it0+aPCYo0TVo#@Y6W+)Ooqbf_n1 z%;OF^=FA<55nc*0T0qfvEb7vgmLPofqp#)6T8=4+ca&!v>wc!2p5W?+IAtV zK@dp5@;uXx%i*SrY`f?mT0czRh(qh zF|g^kW-bHY70%yL;xq9C+f|ifl|k{?L!fmhfwm-}+g6_rFFa-lTU|#{p9n*L=x1t$ zMTB!BE4&vPuI%zENhcX*i{X>I9Sj378|GeJfp2y%gWLNzlg>8DWqq)zA}=~-XbX8c zs5(YP3k`{HV7t7v<~QOJ@pqj)uZrM4HrOtjnUwHs+vPTGce=dj)!0{RCtrL0)*T%y z&JY(q zo*UhRFe91dl7e$VZ)DCxdJAGTqB1-M7%Y4mEg>-#ef^${-|LH7Rre3+$WEHUUWcQQT=0>yi{|PgB?~g_H~8(Gr*@b z$r0X2w@2>|1l7hod08JLB!p4JaCP*KZM}f=?XD1bfZ-!KXSgVos8c(iQcM zy9PA~vhNi-rk!b6*d1PBmX5^RLS3rV_5FPb)*(PIKNU(?zi74Tnh{Fr@DlCQ>Ll@R zPyuba28CGdkWk$%6U`qLHdjR<%QUO>$55kE@rUx$X=QZh;HPJGwpA|t)BSjkA=Hcf zEP+pT_EWO)CCtYoNATlMqWci~7B7`E2UU-GXbY`B=}vqnP4@fH5>S(TISBNc&FM#3u`sI^5F zil5#yYYuiynocGIY)od_-b07j;w#=oAQe;q^&LvUu4J%p2%6Sn!abp{Fmg*G?%q%? z@%yLlb>uSwX}#1N?MyU~wPK%+=IUsn6bOVOAXcMJs_mJpKstYuwU|)iJN#T!U2veZ zAC*iX@e^9wD=mc{HRj;o2ac*;=toymv3B_mMI`6EXMItgzp)edt;uf_%{sLl5z$0v z`U}nJ)>H6}z|J+{>jS405~{A>i#TH2j*@7N-XS8G4EsH7#o!xE2Pkq|N@jfjABhV(bq0hd6w0TCkC8SuCeD|)4Yd9q?L$|(CQk-!aI|2;g`5`fD`NLx<8xvMsj`3zc#WmhR z>1o2&gUH+@|7WFXE`;xW=RBV6Hu=SFS*Cl>$Ck#@68aC5)WP3LEmW#fkQNCf?91 zS&6u*@^T~&x2Z-Va2xbV6Qi<*$;jyA_kw3b#T=v!GF?;=6(?u9FS+#&lha0;?Yf>H zYZBDI{5-S+xO2PhH;}kazfj+OnOe32uty0ZLTjDlV!KrY(C z+9D>y-qsNDY~hh>-snAg^?-p&F#xL|tdf%~0AirMbL#8iGyT;h0R_)R(K>N@Z>ZiZ zVF89hdA)}6#_ zi9f2BdbD}A{#Iz5t!$bl{0CFfX)fUdU-)M*q&euHinO^TXTiroD%n<5S=EaTp9_IAVC zbPHJz*2>wm9n#rX@HMi2D+X7EwJY|S=l7JB_@mbscaOljSY>x$(h5On-U!y7FtZvK ztU`_h`gQ{_8k!K}=Yw|UhXOV!a|GD+d4|{dUXrMUSA>-INO=aS6?42n?Yl9Z;Y8-A z;z&*x8<;&$BL|M-T$tUxKIxFdY=wX&@FndGd_+-~m$JwaAc5%bAlimWL;9wv)xRO9 zC0FA_L;G(l87PuJ%utf1x_*z%QKWjE?*k8bQvdE~FAZIKqAR?Of(W52S~^uw_3+!j zD1cMQf(S0GqYT#Pt2(s*QjzXvQy__$xvsBFKe%oHbMYq>LUp^W>Wh1Mzpmp%P{z;w z^K-1m`C(_R7TwmMCXRq)bd}?mblg@foJBYoN?`;tb$y9&kzO1E?_y?!=8IeoPm^Dd z(`ll3EU&Edgy*dR=y#Vp3?9=6>E4?SHYv3z?88BqWpWq@ygN^xF*g@&Q3uJ_^h|He z=AI$IO@_Zi)MbHlHhmP&|I}>q$KgOOK$x`D0ENAg6m{;E=Av?W*ovgo zoq1(Z|3^tLwOB7|Lj8lwZ9nUxK43BDUQ3@Q2c5vy*7C4eg}FH?RT>sj)J}kVYCNwV zwU{x>q=(F9>2yyClf{ZxIB>yXAvv{aLRkRDH;q`;08gij!WD{B$lE7nv0n!Rg&-mY z{vq;lu%$A0)DUJ=3~&+mieb4biI1@k{S%UDnYoIgttCxoh_6R*;>V0p-xpt026h;- z3usbzWWjdL+?~2@5y)0Io~#;7IpD$#m-&+CRJ+-1;?Cu+CD+LO;n|Twq}{;hEVMB> zS{mAI33AK>j&*wU@VK0#r^9w-)>QjZT9ss#Z!XXQ9zRg^F~9c&W?=%@a@z-W9-rp* z_p}_gSBP!hMGJ?$`6U}VuDFwiS$$ecGwdo{GQ-)=ieb&=Lv&z`4oIBGEhDY8IdSy4 zON`(5h5z0b9=>lm7uk}M9~X32xX}hq=i8SQ)wKKQQ6EL{Jg2w!|^|=868QN=HZ{x5#(d}z$qqlVeq(n6A=hAzpHrE9B5?hD-$c}&9NIF9& zIflgr$%P8tZJf|4yeL&(KicuZ$dH{>^{STV#zrl(((W|?mvT?7^%b889#*4pbpDek z@ID0Jkpd6R%f&%%!4Ya-HVoNicR(mDwXSnc3R_d4m?=qtSC5zt7vL;Xfu}Nb?FPlf zjm{pl3B(7>-Zn%Gw)oeM7jJP!Lf$sAur9B!HiD;iICcU~C&>Vlj-|*Xifs`?YUu`@ z3-5Q+l;_8UU>ln{my!dKa;ped+~^M)Z`X8)`c)#{BhRRxjQy^kb5WdFDbKk$@@DGk zb5Dxt_c=TKp3bPD-V%ZV#~qJci54JYbN62v>5eZ0Oex`l->}xAT}`AQjA$@6I_53V zdnbUa;k;K9X&U6f*k-4Nl1Zxrm|NKC|H6|KMbYt~9&x7qn7=)iJVqh$nSmTJrotsM z)ESd^-IK^ksx;AWiF{0&Y=@75_0xR(VE`>a(!XjVE`1y#uqc63&O0A10B*4m>^h)v zT{R+NS2d4HA0p_Aysnxy)hf*b&WThauF(m|`_10&^ElL6#$yXw+C39drq~*y zlL+=KR_EnPpmgP@&t4n?&OpQ4iOmrRBs8mvqTcl5i;xjl<6dUQ+42?!HRPI6feE#I zxfWYiFZZG3Q%VH^R({4!$x$6DX|r$s>NK&2m4xpcFNNZ7RRf8wDAawI>=)P31#aKU zEm}1w$CTB~-#jQ!3dLai4FqRpo*3C(>G#l5xvNGY#IV-&9SC5;(DW2R5qLczuA2h8 zj(`+r0zzgQKUVs+>pf5Z&8Ptg)wVuePOg6mR2g`!(*h|qj25dB>ZVDPb zon3~6K1WkK^Uvh9Yt($lTEKHdNMjVUed3(bT${W;^DP`B&^*KjiA?g`QDc2fz{srT zXMqHMT`daTfyUs*&~){|_KHoPZ8%?|_A*ljfG&aBh=7X!%8v7bZ7x;P(HTlrD<@0% zL~FCEmmq3_TQ&k?IEDg$So?ch0uTEUro7{a0q>D>_5Hhc8B5*6R9>d;| z+ELShrW+0uV&^;LfJ!8LnK(u?hy~TeXJS@R5fVF%*99!vXTd?3ipu&Mf0jtWi39

    FsI8$8h`*odK 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%0AJNbh|xxi;-J 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

    kSU`Q`X0^9li5j%#}6m{ZP7NMUsbw!B5(H~ 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 z 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
    V`@>=%O$P(eXqwv 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

    m+Z$)-X&9qVLcU0|0j=bC0PQ$w!f^h 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%0D|whH6{PIK1TewOSVcf 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

    =W-1bxx_CAG|8Bg6K5CBKZT@p@O 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 sHiVdD|5`6z#r+%DR*L3Jeqx-sxaH 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 z z5pWtRT|7v7U>Y>Jv+}@FR}BVqc~zQzGVpO04)>~Y!VC^!wRTeUy(DSpwBj%L(3Z+# zVv)YDhb2+mPR53@ZBBOBaPU{+V8$Nh~1C?{-kRM^9g(0yW= zJ)F6@<`AWr9y@=yS&ilpNqngsu!V~=F6R=%eHY{l5p60_Vy5n))@)D+xh2w4N7Dw! ztIssp+6X1>I78&XjaOre3^zX6$BVLL{uA0N11s&+pDp+--N&TGcv7>~kI--<?|#2&_($9w&T%;{>ss|GQu|DmJr)l{x;q={YVV*Gu%Xxp&w} zjJn5IpYv30?RP6>%{zfyWCiDDSc_`7s#qPj2*m)%TN|~*;KnoI5$@I*3-8e&0^wNi z(D)C@?Ku@u>|#r~z*m8TG~(1?FA0$+_`a>-^4CYfHlkTLj$_$7hpOVwE=g+=clQeo z#uQ3zBVP%uS{_Y;*iz6VAL}WbDRbj9lFn;~Lg?{Ix7Zd`_t^h|jpTom*5MDdjD@cY z(())e1+EhuP1$jweyBKI;q+~*$XU?}jQ;rDjy?`V0>s;yScPACYyMr`#&d&HNedyE z+klB0Z5}t#jfPp}a@wJQyJfXv4H7Z|j(Qp01DmX#KdwrCAGOR80~J|9N)+S7XMZ81+AI=Y{~2jQqu#qx z3$hbs-X6-~alLngziozjI3E15*{4*!WAWccakW5<5q4y7TbR05+UB{-Krw8XxKv`V zoAh+&Hedh4Bm|a)9?H}i!g}RtISc?QuiYFFsT*kANEmVzR#~5BTLM__lG4DD^%mt6 zYQ&;fuZRf}gI(Su4E^fXaDb*yt?l|ujPx2A0$<;Ee8PyODr z*|{ewqQ(hIfn^|agCzM$CenAL*~}N)=sO``;JY9a!yt6d<{|0=fT#F*D5A4S$ASOQ zozQ3`mz`BQ2XefY$BWV=SOrkKTWA0}{Rhc0*G+HH8X3WNpSy^~IJ`Lo`@f-owx(TI zll^f895q^tm()XHk9|xzXii15*MD};qRmRk#%5B-v)}Eo6w-HEFA->Oh$h`YU!q$D zL{v@A?AM1#K7#^kmjrj&?A{61dyj^!>TwJ@{EG|EJjpK$wRcnphHbOJs)z!@8N#@e zKy-1Fv>_1sT&nj4v&xjs>tbXIz5p`@h(L=L)Cd(hE^<;4wO_UAxJu#whpv1CQwIMopX&Hp0*ZZN(sk~{ zT`e1s=t& zDqXPr&GNf_NGEt*Ww7B15qys(KX~!J3R=Y;A#ED4DTX*|Re0|TI3a2-#XA9{>ujd5 zlw!@OEE1cj%2tX;a@*o?O&(Q0 z#?A8%cuQzeauYk}DXd0v4L|=#UiMBvcczKU8bbPGqCCY+r89Qi{IuddP_wJ_kbWZ9 zmV-esrILI<)o!CE2}(cTHndS(0+`zn;#jlkDdd(w#xG_Wz42Jee9JA+s2{c7Z z7ZYJqoC%5(bv`sQ(MiFc!M#@u|2$kLgPE7Bm+zt-wiFHM#vkkKccvzUE{e>^a&An3 zpC&iYL_PjQIYa%vQ_UMDCN%F}8pb^-n|P3#wN|cH876N3%;N zvw@0QwCBmf**1S%>A!C0KBI2gZf)hyVHOz9}7xtjQ?z4(f`Q!ZF%YU!voA+M{BZNb9SyjnfS+X~Z@*4b}d zNWmogNA}H8u&Lg$gakf_8R;|TCBa)mD{lkmGzIiUjMdbc=wy16XERZzOb^j z&?tqjd7eE8nxU^+`=)87So%X#P+}F4UEeEeV#os=2@!iUCIw!ur@pk^J@`FWWf#H4 z15RkoRaxd78JUt4fq3X6rS1OM%fBY^fP=DQu5p~n=2-)^M?C1&g-chF?d&E#*|dIN zhqAOoBE20!8SCr1i^6<9(-skbiEjZbS1_n&7~-FQrvEIUeb6|`2eZ4#03HBfqs~J4 z00DOhkI81l;b=H-7;R%{zPJYv1*Umoic*=M=>XV2*mg4!8!P7_ZgOH&#iA|b0v&^# zg=YtwZE{cyJT$&iPw-03h%+O*CCgM2sDA6;Re|%^Sc7=ee#Qj28OvS%7d$Jr*`?c= z`c!14Xiv&Uwk{*INBkN*Gc`il-7!F6xYn8+3Hgpn?NM$B(_dSoQ^{M~>J%MOAT@9$ z)vT+>nx#7?CIL^49n*k}lUN4zm5VJq}xkrsXyZqm3ix`pDkS z23i8M9I;?QGk)zr@l~6OcX9QZSy9qp%Y3P%>O}g;_mWa+%z3EAU5P)MoIUcpIE4Aj z#+Vy5C_9os1t9f~MdyI4ERNYR9zOghF$k)mi4FQ`(t^t0#GNzM&@nS;*b9WfAiE;b zDWg@5$*1*lK;$-KHh-u}=wAaqto?Ag9;@=PIdD3igA9^{TQIFD1@Zlje^Y|i&h>0_Zvb9HpltR5d+D{Wt9(MdKlxf+ zL1pp$Fdy*Rl%&&s(TThBJfXx4Ddt1uXX`2Vu=nYdx%Ck3o>j4_jM9(RfYnB`Wv3J7 z`*IxicsGCXmo8N|_w#8}L?&yJ^PFM3jf*wh9YX++;4A;WE%?VA2yzCdJ$jnb-@E=j zEw8jCHr^=bH`D~<^;`pN0gD2-gCVe-VEqztU-i4=4P~)_Boq3r;d$~l=;SjR!U)M+ zM7#SZF*VclQ*oCql(|vB7Y!$-aj`3vjpstMpJza&<7A;t00gLOQNIUZ1O1^wR?HcwUJm>kCylG`p6XuST6 zF3-Vlg6XLXHTCB@G$0EXy?l!vYSaocp7iPb`OC{vCEVobO|HS}G%@oR@qk)ie>ua|ulWYKmt!FWzp8ESOEsTP2o~|&JnhFJ!_KDfQy1)~L z1w$=B$EdpHg0}#8Aqtemp^}J^q0~fB46BNTfL2|hc_9K($C1lZyE2;6UIv;|t=ZnG zkb;7D6vu53jfEA|&(g0?eoB23iJl?QOzo1b1(K`i^lh{OfsVuYxKy|2=(xHSH+StAWD7e0b?mVh8J>fzscViaH|f)2aJy);u!fqg z3LEd1ets0%q5vN&P|2^!PgpvRFSMwUEkmQ%z0QT!CesEx5F0vd_n~twA&Wwa?E#Dc zG#vT?@Y$Fqtt^5vF+yeoC4>MHyXm1Zpd1ogEy;^N|LpsFWU4*o#$D1HlZ2INm*KLc1_Iw@yx4__@>-Bb_Z{=Vo( z*&j$_1P7tMtKrj8U6V0FOG(#>Z+X+zrQOz60?A-%%+^ZTD?7Mgefz;V4YgdMCF#r4 zE zOBu_IV5zzAcsR7{m`bHp&3!as)M}8?=GyWFDw>T-d0`6sw6)o~TP)UDaISXxX24Til4(w?Hyq)KWiuE@P*NEt-H3r@{>uoONBVnGaP$X(wf z2#l(@NSdr#Z^tobh7;fp#hBYSiO%6mE zl_9wXq+C>MI$+NIk?IqeqO;>ZO`RgW*F8rcMi+*pG$PJn%!~)HR`MD%KB{;Xww#Kx zwJ&n>&l85|X#!sm$lGV?qz}nb()W%2s@}z%l$m-GDs+?a&->>LGbp30A}Y2zZLMSw zeCOKM_1*(W|VT_q;XBHvYq0S1?<2vlMeMeN==F58%l7xC&;vH%0A@iOfC#m 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�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ţ+`OokZJk_ZZAVlsR5W8d; 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%0DDHlL6!_XFNJu?7l+U=5*qJr8 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