From a2f25ab1ca01c98a25e2a98fdf8b96768534a40d Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 12 Jun 2024 10:17:04 -0700 Subject: [PATCH 01/67] Add raw_query fn to GriptapeCloudKnowledgeBaseClient --- .../tool.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 6fed6e618..5f2a726c6 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -5,7 +5,7 @@ from attrs import define, field from griptape.tools.base_griptape_cloud_client import BaseGriptapeCloudClient from griptape.utils.decorators import activity -from griptape.artifacts import TextArtifact, ErrorArtifact +from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact, ErrorArtifact @define @@ -39,6 +39,23 @@ def query(self, params: dict) -> TextArtifact | ErrorArtifact: return TextArtifact(response.text) except exceptions.RequestException as err: return ErrorArtifact(str(err)) + + def raw_query(self, params: dict) -> ListArtifact | 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") + + try: + response = post(url, json={"query": query, "raw": True}, headers=self.headers) + + artifacts: list[BaseArtifact] = [] + for query_result in response.result: + artifacts.append(BaseArtifact.from_json(query_result.meta["artifact"])) + + return ListArtifact(artifacts) + except exceptions.RequestException as err: + return ErrorArtifact(str(err)) def _get_knowledge_base_description(self) -> str: from requests import get From eb3c47e5cb0585faa5b1a88676005ca51ca84e96 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 12 Jun 2024 12:33:27 -0700 Subject: [PATCH 02/67] Re-order Workflow tasks on every task execution wave --- CHANGELOG.md | 1 + griptape/structures/workflow.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 988d2c6c6..6fef1a154 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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. ## [0.26.0] - 2024-06-04 diff --git a/griptape/structures/workflow.py b/griptape/structures/workflow.py index a9c571af2..417dd313f 100644 --- a/griptape/structures/workflow.py +++ b/griptape/structures/workflow.py @@ -92,11 +92,11 @@ def insert_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(): From 1859a7541efd107b52cc410d8b1e2be38b61f476 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 12 Jun 2024 13:31:03 -0700 Subject: [PATCH 03/67] changelog update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0349bbc93..130685c0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `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. +- `GriptapeCloudKnowledgeBaseClient.raw_query()` for receiving raw query responses from the Knowledge Base. ### 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`. From 4aa2eb10aa89d539077544f507487e6c7ad89c99 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 12 Jun 2024 13:50:03 -0700 Subject: [PATCH 04/67] unit tests --- .../tool.py | 5 +++-- ...st_griptape_cloud_knowledge_base_client.py | 22 ++++++++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 5f2a726c6..2dbbc7351 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -39,7 +39,7 @@ def query(self, params: dict) -> TextArtifact | ErrorArtifact: return TextArtifact(response.text) except exceptions.RequestException as err: return ErrorArtifact(str(err)) - + def raw_query(self, params: dict) -> ListArtifact | ErrorArtifact: from requests import post, exceptions @@ -48,9 +48,10 @@ def raw_query(self, params: dict) -> ListArtifact | ErrorArtifact: try: response = post(url, json={"query": query, "raw": True}, headers=self.headers) + response_body = response.json() artifacts: list[BaseArtifact] = [] - for query_result in response.result: + for query_result in response_body.get("result", []): artifacts.append(BaseArtifact.from_json(query_result.meta["artifact"])) return ListArtifact(artifacts) 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..1176fd207 100644 --- a/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py +++ b/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py @@ -1,6 +1,6 @@ import pytest from requests import exceptions -from griptape.artifacts import TextArtifact, ErrorArtifact +from griptape.artifacts import TextArtifact, ErrorArtifact, ListArtifact class TestGriptapeCloudKnowledgeBaseClient: @@ -22,6 +22,19 @@ def client(self, mocker): base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" ) + @pytest.fixture + def client_raw(self, mocker): + from griptape.tools import GriptapeCloudKnowledgeBaseClient + + mock_response = mocker.Mock() + mock_response.status_code = 201 + mock_response.json.return_value = {"result": []} + mocker.patch("requests.post", return_value=mock_response) + + return GriptapeCloudKnowledgeBaseClient( + 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 @@ -67,6 +80,13 @@ 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_raw_query(self, client_raw): + assert isinstance(client_raw.raw_query({"values": {"query": "foo bar"}}), ListArtifact) + + def test_raw_query_error(self, client_kb_error): + assert isinstance(client_kb_error.query({"values": {"query": "foo bar"}}), ErrorArtifact) + assert client_kb_error.raw_query({"values": {"query": "foo bar"}}).value == "error" + def test_get_knowledge_base_description(self, client): assert client._get_knowledge_base_description() == "fizz buzz" From 82f3b469934d03dc88725ea842076bfafaf911f2 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 13 Jun 2024 08:56:49 -0700 Subject: [PATCH 05/67] Consolidate raw into query() --- CHANGELOG.md | 2 +- .../tool.py | 41 +++++++++---------- ...st_griptape_cloud_knowledge_base_client.py | 15 ++++--- 3 files changed, 30 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a078b1a83..b1ca41d03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `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. -- `GriptapeCloudKnowledgeBaseClient.raw_query()` for receiving raw query responses from the Knowledge Base. ### 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`. @@ -55,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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. +- Updated `GriptapeCloudKnowledgeBaseClient.query()` to optionally return raw query responses from the Knowledge Base. ### Fixed - `Workflow.insert_task()` no longer inserts duplicate tasks when given multiple parent tasks. diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 2dbbc7351..da93add20 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -23,38 +23,37 @@ 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, + Literal( + "raw", + description="Return the raw artifacts from the knowledge base instead of a natural language response", + ): bool, + } ), } ) - def query(self, params: dict) -> TextArtifact | ErrorArtifact: + def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: from requests import post, exceptions query = params["values"]["query"] + raw = params["values"].get("raw", False) url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") try: - response = post(url, json={"query": query}, headers=self.headers) + response = post(url, json={"query": query, "raw": raw}, headers=self.headers) - return TextArtifact(response.text) - except exceptions.RequestException as err: - return ErrorArtifact(str(err)) - - def raw_query(self, params: dict) -> ListArtifact | 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") - - try: - response = post(url, json={"query": query, "raw": True}, headers=self.headers) - response_body = response.json() - - artifacts: list[BaseArtifact] = [] - for query_result in response_body.get("result", []): - artifacts.append(BaseArtifact.from_json(query_result.meta["artifact"])) + if raw: + response_body = response.json() + artifacts: list[BaseArtifact] = [] + for query_result in response_body.get("result", []): + artifacts.append(BaseArtifact.from_json(query_result.meta["artifact"])) - return ListArtifact(artifacts) + return ListArtifact(artifacts) + else: + return TextArtifact(response.text) except exceptions.RequestException as err: return ErrorArtifact(str(err)) 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 1176fd207..269063dd2 100644 --- a/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py +++ b/tests/unit/tools/test_griptape_cloud_knowledge_base_client.py @@ -74,18 +74,21 @@ def client_kb_error(self, mocker): ) def test_query(self, client): - assert isinstance(client.query({"values": {"query": "foo bar"}}), TextArtifact) + assert isinstance(client.query({"values": {"query": "foo bar", "raw": False}}), 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_raw_query(self, client_raw): - assert isinstance(client_raw.raw_query({"values": {"query": "foo bar"}}), ListArtifact) + def test_query_raw_default(self, client): + assert isinstance(client.query({"values": {"query": "foo bar"}}), TextArtifact) - def test_raw_query_error(self, client_kb_error): - assert isinstance(client_kb_error.query({"values": {"query": "foo bar"}}), ErrorArtifact) - assert client_kb_error.raw_query({"values": {"query": "foo bar"}}).value == "error" + def test_query_raw(self, client_raw): + assert isinstance(client_raw.query({"values": {"query": "foo bar", "raw": True}}), ListArtifact) + + def test_query_raw_error(self, client_kb_error): + assert isinstance(client_kb_error.query({"values": {"query": "foo bar", "raw": True}}), 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" From 27c080dd271b1dcb698bd7d28add43cf8edc75cb Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 13 Jun 2024 12:33:41 -0700 Subject: [PATCH 06/67] change to query_results in response --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index da93add20..4b05185ee 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -48,7 +48,7 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: if raw: response_body = response.json() artifacts: list[BaseArtifact] = [] - for query_result in response_body.get("result", []): + for query_result in response_body.get("query_results", []): artifacts.append(BaseArtifact.from_json(query_result.meta["artifact"])) return ListArtifact(artifacts) From 53f87fa69223dada8363c881b840b23a4102adc2 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 13 Jun 2024 12:37:59 -0700 Subject: [PATCH 07/67] meta is dict --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 4b05185ee..5ca3ff29b 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -49,7 +49,7 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: response_body = response.json() artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): - artifacts.append(BaseArtifact.from_json(query_result.meta["artifact"])) + artifacts.append(BaseArtifact.from_json(query_result["meta"]["artifact"])) return ListArtifact(artifacts) else: From d045fc543a61600393246a157402877f272634f0 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 18 Jun 2024 10:23:44 -0700 Subject: [PATCH 08/67] add bonus to artifact json --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 5ca3ff29b..0792a9814 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -49,7 +49,8 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: response_body = response.json() artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): - artifacts.append(BaseArtifact.from_json(query_result["meta"]["artifact"])) + artifact_json = query_result["meta"]["bonus"] | query_result["meta"]["artifact"] + artifacts.append(BaseArtifact.from_json(artifact_json)) return ListArtifact(artifacts) else: From a95ddb900146be116cb9b84a206ed29aba8f9d81 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 18 Jun 2024 11:31:32 -0700 Subject: [PATCH 09/67] fix bonus --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 0792a9814..bac87382e 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -3,6 +3,7 @@ from urllib.parse import urljoin from schema import Schema, Literal from attrs import define, field +import json from griptape.tools.base_griptape_cloud_client import BaseGriptapeCloudClient from griptape.utils.decorators import activity from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact, ErrorArtifact @@ -49,8 +50,8 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: response_body = response.json() artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): - artifact_json = query_result["meta"]["bonus"] | query_result["meta"]["artifact"] - artifacts.append(BaseArtifact.from_json(artifact_json)) + artifact_dict = query_result["meta"]["bonus"] | json.loads(query_result["meta"]["artifact"]) + artifacts.append(BaseArtifact.from_dict(artifact_dict)) return ListArtifact(artifacts) else: From 546725ebeb49f00a29ebb93376de9516cece4f97 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 18 Jun 2024 11:37:06 -0700 Subject: [PATCH 10/67] bonus again --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index bac87382e..aaef748b6 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -50,7 +50,8 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: response_body = response.json() artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): - artifact_dict = query_result["meta"]["bonus"] | json.loads(query_result["meta"]["artifact"]) + artifact_dict = json.loads(query_result["meta"]["artifact"]) + artifact_dict["value"] |= query_result["meta"]["bonus"] artifacts.append(BaseArtifact.from_dict(artifact_dict)) return ListArtifact(artifacts) From 3f156f812d378e26b6b1178674712e6d3bed64b0 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 19 Jun 2024 14:10:15 -0700 Subject: [PATCH 11/67] remove keywords from returned artifact --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index aaef748b6..924d1dd25 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -51,6 +51,7 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): artifact_dict = json.loads(query_result["meta"]["artifact"]) + del artifact_dict["Keywords"] artifact_dict["value"] |= query_result["meta"]["bonus"] artifacts.append(BaseArtifact.from_dict(artifact_dict)) From 1fa5fe1ce7608cdb738e269f9703ab01c0549c4c Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 19 Jun 2024 14:16:57 -0700 Subject: [PATCH 12/67] debug --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 1 + 1 file changed, 1 insertion(+) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 924d1dd25..37dbefd5d 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -51,6 +51,7 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): artifact_dict = json.loads(query_result["meta"]["artifact"]) + print(f"Baker: {artifact_dict}") del artifact_dict["Keywords"] artifact_dict["value"] |= query_result["meta"]["bonus"] artifacts.append(BaseArtifact.from_dict(artifact_dict)) From ebdfb40c51eb8297d40edf0154f73f2e560e2aed Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 19 Jun 2024 14:19:31 -0700 Subject: [PATCH 13/67] fix keyword del --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 37dbefd5d..f0dcfcd01 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -51,8 +51,7 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): artifact_dict = json.loads(query_result["meta"]["artifact"]) - print(f"Baker: {artifact_dict}") - del artifact_dict["Keywords"] + del artifact_dict["value"]["Keywords"] artifact_dict["value"] |= query_result["meta"]["bonus"] artifacts.append(BaseArtifact.from_dict(artifact_dict)) From 1a32edc2172a025f6cf7f8ffe2daf7b800b3e50e Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 19 Jun 2024 14:39:41 -0700 Subject: [PATCH 14/67] try/except keywords delete --- griptape/tools/griptape_cloud_knowledge_base_client/tool.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index f0dcfcd01..353fcfd6e 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -51,7 +51,10 @@ def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: artifacts: list[BaseArtifact] = [] for query_result in response_body.get("query_results", []): artifact_dict = json.loads(query_result["meta"]["artifact"]) - del artifact_dict["value"]["Keywords"] + try: + del artifact_dict["value"]["Keywords"] + except KeyError: + pass artifact_dict["value"] |= query_result["meta"]["bonus"] artifacts.append(BaseArtifact.from_dict(artifact_dict)) From faf20ffb5ea5d06b53e544dfe7c9e4dfa2d8ebd2 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 20 Jun 2024 12:08:01 -0700 Subject: [PATCH 15/67] Initial griptape-cloud-vector-store-driver --- CHANGELOG.md | 1 + griptape/artifacts/text_artifact.py | 1 + .../griptape_cloud_vector_store_driver.py | 117 ++++++++++++++++++ 3 files changed, 119 insertions(+) create mode 100644 griptape/drivers/vector/griptape_cloud_vector_store_driver.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 62846b623..85c3d0913 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. +- `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. ### 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/griptape/artifacts/text_artifact.py b/griptape/artifacts/text_artifact.py index e8a2bb2a7..3ad0b8340 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -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) + metadata: dict[str, str] = field(converter=BaseArtifact.value_to_dict, default={}, metadata={"serializable": True}) _embedding: list[float] = field(factory=list, kw_only=True) @property diff --git a/griptape/drivers/vector/griptape_cloud_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_vector_store_driver.py new file mode 100644 index 000000000..91d4dddb6 --- /dev/null +++ b/griptape/drivers/vector/griptape_cloud_vector_store_driver.py @@ -0,0 +1,117 @@ +from urllib.parse import urljoin +import uuid +from typing import Optional, Any +from attrs import Factory, define, field +from dataclasses import dataclass +from griptape.drivers import BaseVectorStoreDriver +from griptape.utils import import_optional_dependency +from sqlalchemy import Column, String, JSON +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.dialects.postgresql import UUID +from requests import post + + +@define +class GriptapeCloudVectorStoreDriver(BaseVectorStoreDriver): + """A vector store driver for Griptape Cloud Knowledge Bases and Data Connectors. + + Attributes: + api_key: API Key for Griptape Cloud. + knowledge_base_id: Knowledge Base ID for Griptape Cloud. + data_connector_ids: List of Data Connectors 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}) + data_connector_ids: list[str] = field(factory=list, 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 + ) + + @knowledge_base_id.validator # pyright: ignore + def validate_knowledge_base_id(self, _, knowledge_base_id: Optional[str]) -> None: + # If data_connector_ids is provided, knowledge_base_id does not need to be provided. + if self.data_connector_ids is not None: + return + + # If data_connector_ids is not provided, knowledge_base_id is required. + if knowledge_base_id is None: + raise ValueError("An knowledge_base_id or data_connector_ids is required") + + @data_connector_ids.validator # pyright: ignore + def validate_data_connector_ids(self, _, data_connector_ids: Optional[list[str]]) -> None: + # If knowledge_base_id is provided, data_connector_ids do not need to be provided. + if self.knowledge_base_id is not None: + return + + # data_connector_ids must be populated if provided. + if (data_connector_ids is not None) and (len(data_connector_ids) == 0): + raise ValueError("data_connector_ids must be populated if provided") + + 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 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.""" + raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") + + 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. + """ + raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") + + def query( + self, + query: str, + count: Optional[int] = BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, + namespace: Optional[str] = None, # TODO: Remove this + include_vectors: bool = False, + distance_metric: str = "cosine_distance", + # GriptapeCloudVectorStoreDriver-specific params: + filter: Optional[dict] = None, + **kwargs, + ) -> list[BaseVectorStoreDriver.QueryResult]: + """Performs a search on the Knowledge Base to find vectors similar to the provided input vector, + optionally filtering to only those that match the provided namespace. + """ + url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") + + request = { + "query": query, + "filters": {}, + "count": count, + "include_vectors": include_vectors, + "distance_metric": distance_metric, + "filter": filter, + } + response_body = post(url, json=request, headers=self.headers).json() + return response_body["query_results"] + + def default_vector_model(self) -> Any: + Vector = import_optional_dependency("pgvector.sqlalchemy").Vector + Base = declarative_base() + + @dataclass + class VectorModel(Base): + __tablename__ = "embeddings" + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) + vector = Column(Vector()) + namespace = Column(String) + meta = Column(JSON) + + return VectorModel + + def delete_vector(self, vector_id: str): + raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") From a9f9008030d672fce0a5e25c4db57e7b412a0d07 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 20 Jun 2024 12:18:54 -0700 Subject: [PATCH 16/67] revert knowledge_base tool changes --- .../tool.py | 34 +++---------------- ...st_griptape_cloud_knowledge_base_client.py | 27 ++------------- 2 files changed, 7 insertions(+), 54 deletions(-) diff --git a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py index 353fcfd6e..6fed6e618 100644 --- a/griptape/tools/griptape_cloud_knowledge_base_client/tool.py +++ b/griptape/tools/griptape_cloud_knowledge_base_client/tool.py @@ -3,10 +3,9 @@ from urllib.parse import urljoin from schema import Schema, Literal from attrs import define, field -import json from griptape.tools.base_griptape_cloud_client import BaseGriptapeCloudClient from griptape.utils.decorators import activity -from griptape.artifacts import BaseArtifact, ListArtifact, TextArtifact, ErrorArtifact +from griptape.artifacts import TextArtifact, ErrorArtifact @define @@ -24,43 +23,20 @@ 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( - "raw", - description="Return the raw artifacts from the knowledge base instead of a natural language response", - ): bool, - } + {Literal("query", description="A natural language search query to run against the knowledge base"): str} ), } ) - def query(self, params: dict) -> TextArtifact | ListArtifact | ErrorArtifact: + def query(self, params: dict) -> TextArtifact | ErrorArtifact: from requests import post, exceptions query = params["values"]["query"] - raw = params["values"].get("raw", False) url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") try: - response = post(url, json={"query": query, "raw": raw}, headers=self.headers) + response = post(url, json={"query": query}, headers=self.headers) - if raw: - response_body = response.json() - artifacts: list[BaseArtifact] = [] - for query_result in response_body.get("query_results", []): - artifact_dict = json.loads(query_result["meta"]["artifact"]) - try: - del artifact_dict["value"]["Keywords"] - except KeyError: - pass - artifact_dict["value"] |= query_result["meta"]["bonus"] - artifacts.append(BaseArtifact.from_dict(artifact_dict)) - - return ListArtifact(artifacts) - else: - return TextArtifact(response.text) + return TextArtifact(response.text) except exceptions.RequestException as err: return ErrorArtifact(str(err)) 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 269063dd2..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,6 +1,6 @@ import pytest from requests import exceptions -from griptape.artifacts import TextArtifact, ErrorArtifact, ListArtifact +from griptape.artifacts import TextArtifact, ErrorArtifact class TestGriptapeCloudKnowledgeBaseClient: @@ -22,19 +22,6 @@ def client(self, mocker): base_url="https://api.griptape.ai", api_key="foo bar", knowledge_base_id="1" ) - @pytest.fixture - def client_raw(self, mocker): - from griptape.tools import GriptapeCloudKnowledgeBaseClient - - mock_response = mocker.Mock() - mock_response.status_code = 201 - mock_response.json.return_value = {"result": []} - mocker.patch("requests.post", return_value=mock_response) - - return GriptapeCloudKnowledgeBaseClient( - 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 @@ -74,22 +61,12 @@ def client_kb_error(self, mocker): ) def test_query(self, client): - assert isinstance(client.query({"values": {"query": "foo bar", "raw": False}}), TextArtifact) + 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_query_raw_default(self, client): - assert isinstance(client.query({"values": {"query": "foo bar"}}), TextArtifact) - - def test_query_raw(self, client_raw): - assert isinstance(client_raw.query({"values": {"query": "foo bar", "raw": True}}), ListArtifact) - - def test_query_raw_error(self, client_kb_error): - assert isinstance(client_kb_error.query({"values": {"query": "foo bar", "raw": True}}), 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" From 5ddf15c67dbf418341cd58992a49a9be26da6743 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 20 Jun 2024 12:19:11 -0700 Subject: [PATCH 17/67] Rename metadata to meta --- griptape/artifacts/text_artifact.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/griptape/artifacts/text_artifact.py b/griptape/artifacts/text_artifact.py index 3ad0b8340..e088d5f07 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -13,7 +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) - metadata: dict[str, str] = field(converter=BaseArtifact.value_to_dict, default={}, metadata={"serializable": True}) + meta: dict[str, str] = field(converter=BaseArtifact.value_to_dict, default={}, metadata={"serializable": True}) _embedding: list[float] = field(factory=list, kw_only=True) @property From 71aed95ee51b85a502509be7095a12d9fabc5091 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 20 Jun 2024 12:20:33 -0700 Subject: [PATCH 18/67] fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 85c3d0913..2e30bd4ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +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. -- `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. +- `GriptapeCloudVectorStoreDriver` to query Griptape Cloud Knowledge Bases. ### 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`. From 0dad40c355ed791282f1deac7f78a6a197a22b0c Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 20 Jun 2024 12:22:06 -0700 Subject: [PATCH 19/67] formatting --- .../vector/griptape_cloud_vector_store_driver.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/griptape/drivers/vector/griptape_cloud_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_vector_store_driver.py index 91d4dddb6..1f42cd59a 100644 --- a/griptape/drivers/vector/griptape_cloud_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_vector_store_driver.py @@ -75,9 +75,9 @@ def query( self, query: str, count: Optional[int] = BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, - namespace: Optional[str] = None, # TODO: Remove this - include_vectors: bool = False, - distance_metric: str = "cosine_distance", + namespace: Optional[str] = None, + include_vectors: Optional[bool] = False, + distance_metric: Optional[str] = "cosine_distance", # GriptapeCloudVectorStoreDriver-specific params: filter: Optional[dict] = None, **kwargs, @@ -89,14 +89,12 @@ def query( request = { "query": query, - "filters": {}, "count": count, - "include_vectors": include_vectors, "distance_metric": distance_metric, "filter": filter, + "include_vectors": include_vectors, } - response_body = post(url, json=request, headers=self.headers).json() - return response_body["query_results"] + return post(url, json=request, headers=self.headers).json()["query_results"] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 09d7ffa98a4e7e42b3b295be17bff9df6c8c0483 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 20 Jun 2024 12:24:35 -0700 Subject: [PATCH 20/67] DC in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e30bd4ab..88a6dde32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +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. -- `GriptapeCloudVectorStoreDriver` to query Griptape Cloud Knowledge Bases. +- `GriptapeCloudVectorStoreDriver` to query Griptape Cloud Knowledge Bases and Data Connectors. ### 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`. From 7539d669127aae678759edcd4b160edabd603830 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 11:07:44 -0700 Subject: [PATCH 21/67] change to KB specific --- ...y => griptape_cloud_knowledge_base_vector_store_driver.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename griptape/drivers/vector/{griptape_cloud_vector_store_driver.py => griptape_cloud_knowledge_base_vector_store_driver.py} (97%) diff --git a/griptape/drivers/vector/griptape_cloud_vector_store_driver.py b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py similarity index 97% rename from griptape/drivers/vector/griptape_cloud_vector_store_driver.py rename to griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py index 1f42cd59a..5ee1f6935 100644 --- a/griptape/drivers/vector/griptape_cloud_vector_store_driver.py +++ b/griptape/drivers/vector/griptape_cloud_knowledge_base_vector_store_driver.py @@ -12,7 +12,7 @@ @define -class GriptapeCloudVectorStoreDriver(BaseVectorStoreDriver): +class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): """A vector store driver for Griptape Cloud Knowledge Bases and Data Connectors. Attributes: @@ -78,7 +78,7 @@ def query( namespace: Optional[str] = None, include_vectors: Optional[bool] = False, distance_metric: Optional[str] = "cosine_distance", - # GriptapeCloudVectorStoreDriver-specific params: + # GriptapeCloudKnowledgeBaseVectorStoreDriver-specific params: filter: Optional[dict] = None, **kwargs, ) -> list[BaseVectorStoreDriver.QueryResult]: From bad50643b02c4ba69d243967eace186a788624df Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 11:12:50 -0700 Subject: [PATCH 22/67] meta changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bd368a51..2aebd2f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ProxyWebScraperDriver` to web scrape using proxies. - Parameter `session` on `AmazonBedrockStructureConfig`. - `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. +- Parameter `meta` on `TextArtifact`. ### 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`. From 74b146ae2a9ac9315948d27436004a262661d027 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 11:19:21 -0700 Subject: [PATCH 23/67] require kb_id --- ...loud_knowledge_base_vector_store_driver.py | 22 ------------------- 1 file changed, 22 deletions(-) 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 5ee1f6935..feb9cf12f 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 @@ -18,39 +18,17 @@ class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): Attributes: api_key: API Key for Griptape Cloud. knowledge_base_id: Knowledge Base ID for Griptape Cloud. - data_connector_ids: List of Data Connectors 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}) - data_connector_ids: list[str] = field(factory=list, 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 ) - @knowledge_base_id.validator # pyright: ignore - def validate_knowledge_base_id(self, _, knowledge_base_id: Optional[str]) -> None: - # If data_connector_ids is provided, knowledge_base_id does not need to be provided. - if self.data_connector_ids is not None: - return - - # If data_connector_ids is not provided, knowledge_base_id is required. - if knowledge_base_id is None: - raise ValueError("An knowledge_base_id or data_connector_ids is required") - - @data_connector_ids.validator # pyright: ignore - def validate_data_connector_ids(self, _, data_connector_ids: Optional[list[str]]) -> None: - # If knowledge_base_id is provided, data_connector_ids do not need to be provided. - if self.knowledge_base_id is not None: - return - - # data_connector_ids must be populated if provided. - if (data_connector_ids is not None) and (len(data_connector_ids) == 0): - raise ValueError("data_connector_ids must be populated if provided") - def upsert_vector( self, vector: list[float], From 19f5cd418d120836de31d0ba86ce328aa6ed566f Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 11:26:16 -0700 Subject: [PATCH 24/67] add to driver init --- griptape/drivers/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 94198b734..208ef947d 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.griptape_cloud_knowledge_base_vector_store_driver import GriptapeCloudKnowledgeBaseVectorStoreDriver from .sql.base_sql_driver import BaseSqlDriver from .sql.amazon_redshift_sql_driver import AmazonRedshiftSqlDriver @@ -142,6 +143,7 @@ "AmazonOpenSearchVectorStoreDriver", "PgVectorVectorStoreDriver", "DummyVectorStoreDriver", + "GriptapeCloudKnowledgeBaseVectorStoreDriver", "BaseSqlDriver", "AmazonRedshiftSqlDriver", "SnowflakeSqlDriver", From 537e6359c5780210b9a9334707dbc45a6ef0593a Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 11:34:43 -0700 Subject: [PATCH 25/67] meta to kw_only --- griptape/artifacts/text_artifact.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/griptape/artifacts/text_artifact.py b/griptape/artifacts/text_artifact.py index e088d5f07..079cfe6f7 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -13,7 +13,9 @@ 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, str] = field(converter=BaseArtifact.value_to_dict, default={}, metadata={"serializable": True}) + meta: dict[str, str] = field( + factory=dict, converter=BaseArtifact.value_to_dict, kw_only=True, metadata={"serializable": True} + ) _embedding: list[float] = field(factory=list, kw_only=True) @property From fa381005f4f048e080b76842d0a475fb4e5e01bf Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 12:06:19 -0700 Subject: [PATCH 26/67] tests --- ...loud_knowledge_base_vector_store_driver.py | 12 +++- ...loud_knowledge_base_vector_store_driver.py | 59 +++++++++++++++++++ 2 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py 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 feb9cf12f..750dbf703 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,14 +1,14 @@ from urllib.parse import urljoin +import requests import uuid from typing import Optional, Any from attrs import Factory, define, field from dataclasses import dataclass -from griptape.drivers import BaseVectorStoreDriver +from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, OpenAiEmbeddingDriver from griptape.utils import import_optional_dependency from sqlalchemy import Column, String, JSON from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.dialects.postgresql import UUID -from requests import post @define @@ -28,6 +28,12 @@ class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): 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: OpenAiEmbeddingDriver(model="text-embedding-ada-002")), + metadata={"serializable": True}, + kw_only=True, + init=False, + ) def upsert_vector( self, @@ -72,7 +78,7 @@ def query( "filter": filter, "include_vectors": include_vectors, } - return post(url, json=request, headers=self.headers).json()["query_results"] + return requests.post(url, json=request, headers=self.headers).json()["entries"] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector 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..35bc4e3ce --- /dev/null +++ b/tests/unit/drivers/vector/test_griptape_cloud_knowledge_base_vector_store_driver.py @@ -0,0 +1,59 @@ +import uuid +from unittest.mock import Mock, patch +from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver + + +class MockResponse: + def __init__(self, json_data, status_code): + self.json_data = json_data + self.status_code = status_code + + def json(self): + return self.json_data + + +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] +test_entries = { + "entries": [ + { + "id": test_ids[0], + "vector": test_vecs[0], + "namespace": test_namespaces[0], + "meta": test_metas[0], + "score": test_scores[0], + }, + { + "id": test_ids[1], + "vector": test_vecs[1], + "namespace": test_namespaces[1], + "meta": test_metas[1], + "score": test_scores[1], + }, + ] +} + + +class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: + def mock_requests_post(*args, **kwargs): + return MockResponse({"entries": test_entries}, 404) + + @patch("requests.post", side_effect=mock_requests_post) + def test_query(self, mock_post): + driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key="foo", knowledge_base_id="bar") + + result = driver.query("some query", include_vectors=True) + + assert result["entries"][0]["id"] == test_ids[0] + assert result["entries"][1]["id"] == test_ids[1] + assert result["entries"][0]["vector"] == test_vecs[0] + assert result["entries"][1]["vector"] == test_vecs[1] + assert result["entries"][0]["namespace"] == test_namespaces[0] + assert result["entries"][1]["namespace"] == test_namespaces[1] + assert result["entries"][0]["meta"] == test_metas[0] + assert result["entries"][1]["meta"] == test_metas[1] + assert result["entries"][0]["score"] == test_scores[0] + assert result["entries"][1]["score"] == test_scores[1] From 306fa0f8e7fe5062e06fee33a0ff495424ce7038 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 12:12:11 -0700 Subject: [PATCH 27/67] doc improvement --- .../vector/griptape_cloud_knowledge_base_vector_store_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 750dbf703..7e2b7755f 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,7 +67,7 @@ def query( **kwargs, ) -> list[BaseVectorStoreDriver.QueryResult]: """Performs a search on the Knowledge Base to find vectors similar to the provided input vector, - optionally filtering to only those that match the provided namespace. + 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") From 6ab7890aed272bd41e29c3c7ee947947ffa2b504 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 12:56:26 -0700 Subject: [PATCH 28/67] use dummy embed driver --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) 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 7e2b7755f..3a5f48297 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 @@ -4,7 +4,7 @@ from typing import Optional, Any from attrs import Factory, define, field from dataclasses import dataclass -from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, OpenAiEmbeddingDriver +from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver from griptape.utils import import_optional_dependency from sqlalchemy import Column, String, JSON from sqlalchemy.ext.declarative import declarative_base @@ -29,10 +29,7 @@ class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): default=Factory(lambda self: {"Authorization": f"Bearer {self.api_key}"}, takes_self=True), kw_only=True ) embedding_driver: BaseEmbeddingDriver = field( - default=Factory(lambda: OpenAiEmbeddingDriver(model="text-embedding-ada-002")), - metadata={"serializable": True}, - kw_only=True, - init=False, + default=Factory(lambda: DummyEmbeddingDriver()), metadata={"serializable": True}, kw_only=True, init=False ) def upsert_vector( From 159d7b6dd30d7f490e5f336444af564241c5ee57 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 13:08:01 -0700 Subject: [PATCH 29/67] test --- .../vector/griptape_cloud_knowledge_base_vector_store_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3a5f48297..5f499ff72 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 @@ -75,7 +75,7 @@ def query( "filter": filter, "include_vectors": include_vectors, } - return requests.post(url, json=request, headers=self.headers).json()["entries"] + return requests.post(url, json=request, headers=self.headers).json() def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 60532e3b6925313709fd6aab77a88f414dcf4558 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 13:22:04 -0700 Subject: [PATCH 30/67] only include optional params if defined --- ...loud_knowledge_base_vector_store_driver.py | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) 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 5f499ff72..de248b744 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 @@ -57,8 +57,8 @@ def query( query: str, count: Optional[int] = BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, namespace: Optional[str] = None, - include_vectors: Optional[bool] = False, - distance_metric: Optional[str] = "cosine_distance", + include_vectors: Optional[bool] = None, + distance_metric: Optional[str] = None, # GriptapeCloudKnowledgeBaseVectorStoreDriver-specific params: filter: Optional[dict] = None, **kwargs, @@ -68,13 +68,16 @@ def query( """ url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") - request = { - "query": query, - "count": count, - "distance_metric": distance_metric, - "filter": filter, - "include_vectors": include_vectors, - } + request: dict[str, Any] = {"query": query} + if count is not None: + request["count"] = count + if distance_metric is not None: + request["distance_metric"] = distance_metric + if filter is not None: + request["filter"] = filter + if include_vectors is not None: + request["include_vectors"] = include_vectors + return requests.post(url, json=request, headers=self.headers).json() def default_vector_model(self) -> Any: From e14ee75d67e637fb06469b6655017d892016031a Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 13:28:42 -0700 Subject: [PATCH 31/67] remove converter from meta --- griptape/artifacts/text_artifact.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/griptape/artifacts/text_artifact.py b/griptape/artifacts/text_artifact.py index 079cfe6f7..05064f53c 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -13,9 +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, str] = field( - factory=dict, converter=BaseArtifact.value_to_dict, kw_only=True, metadata={"serializable": True} - ) + meta: dict[str, str] = field(factory=dict, kw_only=True, metadata={"serializable": True}) _embedding: list[float] = field(factory=list, kw_only=True) @property From 6fefbea4a83b30cda9b8d27d3edca62e6aca9c20 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 13:46:37 -0700 Subject: [PATCH 32/67] debug --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) 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 de248b744..2b07e2068 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 @@ -78,7 +78,11 @@ def query( if include_vectors is not None: request["include_vectors"] = include_vectors - return requests.post(url, json=request, headers=self.headers).json() + response = requests.post(url, json=request, headers=self.headers) + print(response) + json_response = response.json() + print(json_response) + return json_response def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From bde14fe23ab280e0a7eb234604da4615c6deb1fb Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 14:00:35 -0700 Subject: [PATCH 33/67] remove debug --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) 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 2b07e2068..de248b744 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 @@ -78,11 +78,7 @@ def query( if include_vectors is not None: request["include_vectors"] = include_vectors - response = requests.post(url, json=request, headers=self.headers) - print(response) - json_response = response.json() - print(json_response) - return json_response + return requests.post(url, json=request, headers=self.headers).json() def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 35ac22aaa3416a7d887f9f97f2676f5c32358551 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 14:35:04 -0700 Subject: [PATCH 34/67] debug --- griptape/tools/vector_store_client/tool.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index f2dc785b0..bc7786d82 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -5,6 +5,7 @@ from griptape.artifacts import BaseArtifact, ErrorArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity +import traceback @define @@ -42,4 +43,6 @@ def search(self, params: dict) -> BaseArtifact: try: return self.query_engine.query(query, top_n=self.top_n, namespace=self.namespace) except Exception as e: + print(e) + print(traceback.format_exc()) return ErrorArtifact(f"error querying vector store: {e}") From ab8da26372907f09bafe79e809446dd0980de3f4 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 14:39:41 -0700 Subject: [PATCH 35/67] debug 2 --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 de248b744..e45c277f2 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 @@ -78,7 +78,9 @@ def query( if include_vectors is not None: request["include_vectors"] = include_vectors - return requests.post(url, json=request, headers=self.headers).json() + response = requests.post(url, json=request, headers=self.headers).json() + print(response) + return response def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 750f675a40403f9d1070397a6b98a707121b1460 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 14:45:03 -0700 Subject: [PATCH 36/67] fix? --- ...ape_cloud_knowledge_base_vector_store_driver.py | 14 +++++++++++--- griptape/tools/vector_store_client/tool.py | 3 --- 2 files changed, 11 insertions(+), 6 deletions(-) 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 e45c277f2..52b34ac05 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 @@ -78,9 +78,17 @@ def query( if include_vectors is not None: request["include_vectors"] = include_vectors - response = requests.post(url, json=request, headers=self.headers).json() - print(response) - return response + results = requests.post(url, json=request, headers=self.headers).json() + return [ + BaseVectorStoreDriver.QueryResult( + id=result[0].id, + vector=result[0].vector, + score=result[0].score, + meta=result[0].meta, + namespace=result[0].namespace, + ) + for result in results + ] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector diff --git a/griptape/tools/vector_store_client/tool.py b/griptape/tools/vector_store_client/tool.py index bc7786d82..f2dc785b0 100644 --- a/griptape/tools/vector_store_client/tool.py +++ b/griptape/tools/vector_store_client/tool.py @@ -5,7 +5,6 @@ from griptape.artifacts import BaseArtifact, ErrorArtifact from griptape.tools import BaseTool from griptape.utils.decorators import activity -import traceback @define @@ -43,6 +42,4 @@ def search(self, params: dict) -> BaseArtifact: try: return self.query_engine.query(query, top_n=self.top_n, namespace=self.namespace) except Exception as e: - print(e) - print(traceback.format_exc()) return ErrorArtifact(f"error querying vector store: {e}") From 1d2d6ad769fd903d50a9158c1e6e2d3edc451edb Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 15:00:28 -0700 Subject: [PATCH 37/67] fix ?? --- ...iptape_cloud_knowledge_base_vector_store_driver.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) 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 52b34ac05..053a5b586 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 @@ -79,16 +79,7 @@ def query( request["include_vectors"] = include_vectors results = requests.post(url, json=request, headers=self.headers).json() - return [ - BaseVectorStoreDriver.QueryResult( - id=result[0].id, - vector=result[0].vector, - score=result[0].score, - meta=result[0].meta, - namespace=result[0].namespace, - ) - for result in results - ] + return [BaseVectorStoreDriver.QueryResult(**result) for result in results] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 3f3c6229fb15049f1153937410d41aadbd6bdcea Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 15:03:23 -0700 Subject: [PATCH 38/67] json load --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 053a5b586..ab3bdbe24 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,4 +1,5 @@ from urllib.parse import urljoin +import json import requests import uuid from typing import Optional, Any @@ -79,7 +80,7 @@ def query( request["include_vectors"] = include_vectors results = requests.post(url, json=request, headers=self.headers).json() - return [BaseVectorStoreDriver.QueryResult(**result) for result in results] + return [BaseVectorStoreDriver.QueryResult(**json.loads(result)) for result in results] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 373d353bd7ebb528f8fd41655eb4c7078c02b14e Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 15:06:24 -0700 Subject: [PATCH 39/67] debug part 176 --- .../vector/griptape_cloud_knowledge_base_vector_store_driver.py | 2 ++ 1 file changed, 2 insertions(+) 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 ab3bdbe24..db4a96140 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 @@ -80,6 +80,8 @@ def query( request["include_vectors"] = include_vectors results = requests.post(url, json=request, headers=self.headers).json() + print(results[0]) + print(type(results[0])) return [BaseVectorStoreDriver.QueryResult(**json.loads(result)) for result in results] def default_vector_model(self) -> Any: From a9d857ea010af2b7185f07972df7ca6018e63b99 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 15:10:06 -0700 Subject: [PATCH 40/67] moar debug --- ...iptape_cloud_knowledge_base_vector_store_driver.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) 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 db4a96140..b0c8567ac 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 @@ -79,10 +79,13 @@ def query( if include_vectors is not None: request["include_vectors"] = include_vectors - results = requests.post(url, json=request, headers=self.headers).json() - print(results[0]) - print(type(results[0])) - return [BaseVectorStoreDriver.QueryResult(**json.loads(result)) for result in results] + response = requests.post(url, json=request, headers=self.headers) + print(response) + print(type(response)) + json_response = response.json() + print(json_response) + print(type(json_response)) + return [BaseVectorStoreDriver.QueryResult(**json.loads(result)) for result in json_response] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From ee0dafa79de90e5eaac93ecfeb8362b3b7ba65b4 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 15:14:56 -0700 Subject: [PATCH 41/67] get entry --- ...riptape_cloud_knowledge_base_vector_store_driver.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) 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 b0c8567ac..918311b87 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 @@ -79,13 +79,9 @@ def query( if include_vectors is not None: request["include_vectors"] = include_vectors - response = requests.post(url, json=request, headers=self.headers) - print(response) - print(type(response)) - json_response = response.json() - print(json_response) - print(type(json_response)) - return [BaseVectorStoreDriver.QueryResult(**json.loads(result)) for result in json_response] + response = requests.post(url, json=request, headers=self.headers).json() + entries = response.get("entries", []) + return [BaseVectorStoreDriver.QueryResult(**json.loads(entry)) for entry in entries] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 6ea54bb763365002cc992a07a58184c4c8d66158 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 15:18:32 -0700 Subject: [PATCH 42/67] remove json loads --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 918311b87..4ec8e5f71 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,5 +1,4 @@ from urllib.parse import urljoin -import json import requests import uuid from typing import Optional, Any @@ -81,7 +80,7 @@ def query( response = requests.post(url, json=request, headers=self.headers).json() entries = response.get("entries", []) - return [BaseVectorStoreDriver.QueryResult(**json.loads(entry)) for entry in entries] + return [BaseVectorStoreDriver.QueryResult(**entry) for entry in entries] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 654155a158785f43569f0d17a60ecc6eb1981d25 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 21 Jun 2024 15:29:38 -0700 Subject: [PATCH 43/67] not-implemented upserts --- ...e_cloud_knowledge_base_vector_store_driver.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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 4ec8e5f71..1ddf46033 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 @@ -4,6 +4,7 @@ from typing import Optional, Any from attrs import Factory, define, field from dataclasses import dataclass +from griptape.artifacts import TextArtifact from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver from griptape.utils import import_optional_dependency from sqlalchemy import Column, String, JSON @@ -42,6 +43,21 @@ def upsert_vector( ) -> 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, **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: """Retrieves a specific vector entry from the collection based on its identifier and optional namespace.""" raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") From 432bb113f1885e085a7d7a0982af37d1b739b5df Mon Sep 17 00:00:00 2001 From: cjkindel Date: Mon, 24 Jun 2024 10:04:22 -0700 Subject: [PATCH 44/67] Update for RAGEngine --- ...loud_knowledge_base_vector_store_driver.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) 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 1ddf46033..7808baa1a 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 @@ -4,7 +4,7 @@ from typing import Optional, Any from attrs import Factory, define, field from dataclasses import dataclass -from griptape.artifacts import TextArtifact +from griptape.artifacts import TextArtifact, ListArtifact from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver from griptape.utils import import_optional_dependency from sqlalchemy import Column, String, JSON @@ -44,7 +44,12 @@ def upsert_vector( 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, **kwargs + 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.") @@ -68,6 +73,12 @@ def load_entries(self, namespace: Optional[str] = None) -> list[BaseVectorStoreD """ raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") + def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: + """Retrieves all Artifacts from the collection, optionally filtering to only + those that match the provided namespace. + """ + raise NotImplementedError(f"{self.__class__.__name__} does not support Artifact loading.") + def query( self, query: str, @@ -78,7 +89,7 @@ def query( # GriptapeCloudKnowledgeBaseVectorStoreDriver-specific params: filter: Optional[dict] = None, **kwargs, - ) -> list[BaseVectorStoreDriver.QueryResult]: + ) -> list[BaseVectorStoreDriver.Entry]: """Performs a search on the Knowledge Base to find vectors similar to the provided input vector, optionally filtering to only those that match the provided filter(s). """ @@ -96,7 +107,7 @@ def query( response = requests.post(url, json=request, headers=self.headers).json() entries = response.get("entries", []) - return [BaseVectorStoreDriver.QueryResult(**entry) for entry in entries] + return [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] def default_vector_model(self) -> Any: Vector = import_optional_dependency("pgvector.sqlalchemy").Vector From 586fd25868a109a195282ab81a035e98c2da9e12 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Mon, 24 Jun 2024 10:13:50 -0700 Subject: [PATCH 45/67] remove meta change --- CHANGELOG.md | 1 - griptape/artifacts/text_artifact.py | 1 - 2 files changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ad4b9a69..4daa6b7d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ProxyWebScraperDriver` to web scrape using proxies. - Parameter `session` on `AmazonBedrockStructureConfig`. - `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. -- 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 05064f53c..e8a2bb2a7 100644 --- a/griptape/artifacts/text_artifact.py +++ b/griptape/artifacts/text_artifact.py @@ -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, str] = field(factory=dict, kw_only=True, metadata={"serializable": True}) _embedding: list[float] = field(factory=list, kw_only=True) @property From 8183f26721bdbbdf7e45a7f4a22353b9afecfb43 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Mon, 24 Jun 2024 10:54:16 -0700 Subject: [PATCH 46/67] fix tests --- ...loud_knowledge_base_vector_store_driver.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) 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 35bc4e3ce..a0c2b74d8 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 @@ -39,7 +39,7 @@ def json(self): class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: def mock_requests_post(*args, **kwargs): - return MockResponse({"entries": test_entries}, 404) + return MockResponse(test_entries, 404) @patch("requests.post", side_effect=mock_requests_post) def test_query(self, mock_post): @@ -47,13 +47,13 @@ def test_query(self, mock_post): result = driver.query("some query", include_vectors=True) - assert result["entries"][0]["id"] == test_ids[0] - assert result["entries"][1]["id"] == test_ids[1] - assert result["entries"][0]["vector"] == test_vecs[0] - assert result["entries"][1]["vector"] == test_vecs[1] - assert result["entries"][0]["namespace"] == test_namespaces[0] - assert result["entries"][1]["namespace"] == test_namespaces[1] - assert result["entries"][0]["meta"] == test_metas[0] - assert result["entries"][1]["meta"] == test_metas[1] - assert result["entries"][0]["score"] == test_scores[0] - assert result["entries"][1]["score"] == test_scores[1] + assert result[0].id == test_ids[0] + assert result[1].id == test_ids[1] + assert result[0].vector == test_vecs[0] + assert result[1].vector == test_vecs[1] + assert result[0].namespace == test_namespaces[0] + assert result[1].namespace == test_namespaces[1] + assert result[0].meta == test_metas[0] + assert result[1].meta == test_metas[1] + assert result[0].score == test_scores[0] + assert result[1].score == test_scores[1] From a61180d23da9943c17fe05fd4d5a56775a8f2ce9 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 10:32:06 -0700 Subject: [PATCH 47/67] more tests --- ...loud_knowledge_base_vector_store_driver.py | 21 ----------------- ...loud_knowledge_base_vector_store_driver.py | 23 +++++++++++++++++-- 2 files changed, 21 insertions(+), 23 deletions(-) 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 7808baa1a..5bb548097 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,15 +1,9 @@ from urllib.parse import urljoin import requests -import uuid from typing import Optional, Any from attrs import Factory, define, field -from dataclasses import dataclass from griptape.artifacts import TextArtifact, ListArtifact from griptape.drivers import BaseEmbeddingDriver, BaseVectorStoreDriver, DummyEmbeddingDriver -from griptape.utils import import_optional_dependency -from sqlalchemy import Column, String, JSON -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.dialects.postgresql import UUID @define @@ -109,20 +103,5 @@ def query( entries = response.get("entries", []) return [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] - def default_vector_model(self) -> Any: - Vector = import_optional_dependency("pgvector.sqlalchemy").Vector - Base = declarative_base() - - @dataclass - class VectorModel(Base): - __tablename__ = "embeddings" - - id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, unique=True, nullable=False) - vector = Column(Vector()) - namespace = Column(String) - meta = Column(JSON) - - return VectorModel - 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 index a0c2b74d8..ebabe06ce 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 @@ -39,13 +39,32 @@ def json(self): class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: def mock_requests_post(*args, **kwargs): - return MockResponse(test_entries, 404) + return MockResponse(test_entries, 200) @patch("requests.post", side_effect=mock_requests_post) def test_query(self, mock_post): driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key="foo", knowledge_base_id="bar") - result = driver.query("some query", include_vectors=True) + result = driver.query( + "some query", count=10, namespace="foo", include_vectors=True, distance_metric="bar", filter={"foo": "bar"} + ) + + assert result[0].id == test_ids[0] + assert result[1].id == test_ids[1] + assert result[0].vector == test_vecs[0] + assert result[1].vector == test_vecs[1] + assert result[0].namespace == test_namespaces[0] + assert result[1].namespace == test_namespaces[1] + assert result[0].meta == test_metas[0] + assert result[1].meta == test_metas[1] + assert result[0].score == test_scores[0] + assert result[1].score == test_scores[1] + + @patch("requests.post", side_effect=mock_requests_post) + def test_query_defaults(self, mock_post): + driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key="foo", knowledge_base_id="bar") + + result = driver.query("some query") assert result[0].id == test_ids[0] assert result[1].id == test_ids[1] From 851736eddd0ac1c728ef475f9c0db57b3ee9ea30 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 10:42:25 -0700 Subject: [PATCH 48/67] change default count --- .../vector/griptape_cloud_knowledge_base_vector_store_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5bb548097..eac32d597 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 @@ -76,7 +76,7 @@ def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: def query( self, query: str, - count: Optional[int] = BaseVectorStoreDriver.DEFAULT_QUERY_COUNT, + count: Optional[int] = None, namespace: Optional[str] = None, include_vectors: Optional[bool] = None, distance_metric: Optional[str] = None, From 53101c1c0b313eb0408bcf2636f95f2fc1d2537e Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 11:33:18 -0700 Subject: [PATCH 49/67] debug --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 eac32d597..20ffe4894 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 @@ -100,8 +100,11 @@ def query( request["include_vectors"] = include_vectors response = requests.post(url, json=request, headers=self.headers).json() + print(f"Baker: {response}") entries = response.get("entries", []) - return [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] + entry_list = [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] + print(f"Kulshan: {entry_list}") + return entry_list def delete_vector(self, vector_id: str): raise NotImplementedError(f"{self.__class__.__name__} does not support deletion.") From 88cd303972be96d6182180e7d5355ad0cba8fcd5 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 11:41:44 -0700 Subject: [PATCH 50/67] remove debug --- .../vector/griptape_cloud_knowledge_base_vector_store_driver.py | 2 -- 1 file changed, 2 deletions(-) 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 20ffe4894..93809186e 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 @@ -100,10 +100,8 @@ def query( request["include_vectors"] = include_vectors response = requests.post(url, json=request, headers=self.headers).json() - print(f"Baker: {response}") entries = response.get("entries", []) entry_list = [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] - print(f"Kulshan: {entry_list}") return entry_list def delete_vector(self, vector_id: str): From f693b14be0dff9e1f2e479a0f6c435bc29902c5a Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 13:42:05 -0700 Subject: [PATCH 51/67] append meta to value post-query --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 93809186e..fc4ed1285 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 @@ -101,7 +101,10 @@ def query( 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] + entry_list = [] + for entry in entries: + entry["meta"]["artifact"]["value"] |= entry["meta"]["artifact"]["meta"] + entry_list.append(BaseVectorStoreDriver.Entry.from_dict(entry)) return entry_list def delete_vector(self, vector_id: str): From af6d13aca66eccac275e9f222bed8567f5eacc71 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 13:46:13 -0700 Subject: [PATCH 52/67] debug --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 fc4ed1285..c88518846 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 @@ -103,7 +103,10 @@ def query( entries = response.get("entries", []) entry_list = [] for entry in entries: - entry["meta"]["artifact"]["value"] |= entry["meta"]["artifact"]["meta"] + print(entry) + print(entry["meta"]["artifact"]["meta"]) + print(entry["meta"]["artifact"]["value"]) + # entry["meta"]["artifact"]["value"] |= entry["meta"]["artifact"]["meta"] entry_list.append(BaseVectorStoreDriver.Entry.from_dict(entry)) return entry_list From 6b6389a8fd015853474d0916b91ec087ffd5e0b5 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 13:50:25 -0700 Subject: [PATCH 53/67] moar debug --- .../vector/griptape_cloud_knowledge_base_vector_store_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c88518846..9fba2fc13 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 @@ -103,7 +103,7 @@ def query( entries = response.get("entries", []) entry_list = [] for entry in entries: - print(entry) + print(f"Baker: {entry['meta']}") print(entry["meta"]["artifact"]["meta"]) print(entry["meta"]["artifact"]["value"]) # entry["meta"]["artifact"]["value"] |= entry["meta"]["artifact"]["meta"] From 5d0cd17f2ddcedc813923af72afbf0f0e2d6db0b Mon Sep 17 00:00:00 2001 From: cjkindel Date: Tue, 25 Jun 2024 13:53:54 -0700 Subject: [PATCH 54/67] remove debug --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) 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 9fba2fc13..93809186e 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 @@ -101,13 +101,7 @@ def query( response = requests.post(url, json=request, headers=self.headers).json() entries = response.get("entries", []) - entry_list = [] - for entry in entries: - print(f"Baker: {entry['meta']}") - print(entry["meta"]["artifact"]["meta"]) - print(entry["meta"]["artifact"]["value"]) - # entry["meta"]["artifact"]["value"] |= entry["meta"]["artifact"]["meta"] - entry_list.append(BaseVectorStoreDriver.Entry.from_dict(entry)) + entry_list = [BaseVectorStoreDriver.Entry.from_dict(entry) for entry in entries] return entry_list def delete_vector(self, vector_id: str): From b3379729707efdd58f0c134ad9e289c9535514f2 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 26 Jun 2024 07:33:46 -0700 Subject: [PATCH 55/67] remove DC from comment --- .../vector/griptape_cloud_knowledge_base_vector_store_driver.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 93809186e..a5fd19828 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 @@ -8,7 +8,7 @@ @define class GriptapeCloudKnowledgeBaseVectorStoreDriver(BaseVectorStoreDriver): - """A vector store driver for Griptape Cloud Knowledge Bases and Data Connectors. + """A vector store driver for Griptape Cloud Knowledge Bases. Attributes: api_key: API Key for Griptape Cloud. From d0872a0b675907069bd836ac1d8451241127f67e Mon Sep 17 00:00:00 2001 From: cjkindel Date: Wed, 3 Jul 2024 10:15:41 -0700 Subject: [PATCH 56/67] update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f1a89505..8790687d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,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. +- `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. ### Changed - **BREAKING**: Moved/renamed `griptape.utils.PromptStack` to `griptape.common.PromptStack`. @@ -68,7 +69,6 @@ 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. -- `GriptapeCloudKnowledgeBaseVectorStoreDriver` to query Griptape Cloud Knowledge Bases. ### 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. From 6e136867e9565bbd21063c9b330fff62ef8e43f5 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 09:58:33 -0700 Subject: [PATCH 57/67] clean up request gen --- ..._cloud_knowledge_base_vector_store_driver.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) 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 a5fd19828..08a2a643a 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 @@ -89,15 +89,14 @@ def query( """ url = urljoin(self.base_url.strip("/"), f"/api/knowledge-bases/{self.knowledge_base_id}/query") - request: dict[str, Any] = {"query": query} - if count is not None: - request["count"] = count - if distance_metric is not None: - request["distance_metric"] = distance_metric - if filter is not None: - request["filter"] = filter - if include_vectors is not None: - request["include_vectors"] = include_vectors + 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", []) From cbeb422ff1f44b0c97ec8d52d154d86c0ab5e399 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 09:58:56 -0700 Subject: [PATCH 58/67] reformat tests --- ...loud_knowledge_base_vector_store_driver.py | 111 +++++++++--------- 1 file changed, 56 insertions(+), 55 deletions(-) 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 ebabe06ce..0778d3d37 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,6 +1,5 @@ +import pytest import uuid -from unittest.mock import Mock, patch -from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver class MockResponse: @@ -12,67 +11,69 @@ def json(self): return self.json_data -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] -test_entries = { - "entries": [ - { - "id": test_ids[0], - "vector": test_vecs[0], - "namespace": test_namespaces[0], - "meta": test_metas[0], - "score": test_scores[0], - }, - { - "id": test_ids[1], - "vector": test_vecs[1], - "namespace": test_namespaces[1], - "meta": test_metas[1], - "score": test_scores[1], - }, - ] -} +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): + from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver -class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: - def mock_requests_post(*args, **kwargs): - return MockResponse(test_entries, 200) + 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], + }, + ] + } - @patch("requests.post", side_effect=mock_requests_post) - def test_query(self, mock_post): - driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key="foo", knowledge_base_id="bar") + 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 == test_ids[0] - assert result[1].id == test_ids[1] - assert result[0].vector == test_vecs[0] - assert result[1].vector == test_vecs[1] - assert result[0].namespace == test_namespaces[0] - assert result[1].namespace == test_namespaces[1] - assert result[0].meta == test_metas[0] - assert result[1].meta == test_metas[1] - assert result[0].score == test_scores[0] - assert result[1].score == test_scores[1] - - @patch("requests.post", side_effect=mock_requests_post) - def test_query_defaults(self, mock_post): - driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key="foo", knowledge_base_id="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 == test_ids[0] - assert result[1].id == test_ids[1] - assert result[0].vector == test_vecs[0] - assert result[1].vector == test_vecs[1] - assert result[0].namespace == test_namespaces[0] - assert result[1].namespace == test_namespaces[1] - assert result[0].meta == test_metas[0] - assert result[1].meta == test_metas[1] - assert result[0].score == test_scores[0] - assert result[1].score == test_scores[1] + 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 a33b3377a2b24a2252ac09300766c433bed2d2f2 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 09:59:12 -0700 Subject: [PATCH 59/67] add docs --- .../drivers/vector-store-drivers.md | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index da6fdc242..834f0ac72 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -49,6 +49,30 @@ 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 support, 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["GT_CLOUD_API_KEY"] +gt_cloud_knowledge_base_id = os.environ["GT_CLOUD_KNOWLEDGE_BASE_ID"] + +vector_store_driver = GriptapeCloudKnowledgeBaseVectorStoreDriver(api_key=gt_cloud_api_key, knowledge_base_id=gt_cloud_knowledge_base_id) + +result = vector_store_driver.query(query="What is griptape?") + +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) + +``` + ### Pinecone !!! info @@ -127,7 +151,7 @@ prompt_driver = OpenAiChatPromptDriver(model="gpt-3.5-turbo") namespace = 'griptape-ai' # Initialize the vector store driver -vector_store = MarqoVectorStoreDriver( +vector_store_driver = MarqoVectorStoreDriver( api_key=os.environ["MARQO_API_KEY"], url=os.environ["MARQO_URL"], index=os.environ["MARQO_INDEX_NAME"], @@ -138,13 +162,13 @@ vector_store = MarqoVectorStoreDriver( artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") # Upsert the artifacts into the vector store -vector_store.upsert_text_artifacts( +vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store.query(query="What is griptape?") +result = vector_store_driver.query(query="What is griptape?") print(result) ``` @@ -174,7 +198,7 @@ index_name = os.environ["MONGODB_INDEX_NAME"] vector_path = os.environ["MONGODB_VECTOR_PATH"] # Initialize the vector store driver -vector_store = MongoDbAtlasVectorStoreDriver( +vector_store_driver = MongoDbAtlasVectorStoreDriver( connection_string=f"mongodb+srv://{username}:{password}@{host}/{database_name}", database_name=database_name, collection_name=collection_name, @@ -187,13 +211,13 @@ vector_store = MongoDbAtlasVectorStoreDriver( artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") # Upsert the artifacts into the vector store -vector_store.upsert_text_artifacts( +vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store.query(query="What is griptape?") +result = vector_store_driver.query(query="What is griptape?") print(result) ``` @@ -242,7 +266,7 @@ index_name = os.environ["AZURE_MONGODB_INDEX_NAME"] vector_path = os.environ["AZURE_MONGODB_VECTOR_PATH"] # Initialize the vector store driver -vector_store = AzureMongoDbVectorStoreDriver( +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, @@ -255,13 +279,13 @@ vector_store = AzureMongoDbVectorStoreDriver( artifacts = WebLoader(max_tokens=200).load("https://www.griptape.ai") # Upsert the artifacts into the vector store -vector_store.upsert_text_artifacts( +vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, } ) -result = vector_store.query(query="What is griptape?") +result = vector_store_driver.query(query="What is griptape?") print(result) ``` @@ -403,7 +427,7 @@ vector_store_driver.upsert_text_artifacts( } ) -result = vector_store_driver.query("What is griptape?") +result = vector_store_driver.query(query="What is griptape?") print(result) ``` From 298e5435212ba05dc594fa9ed2b87d9a9b9c454e Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 10:20:46 -0700 Subject: [PATCH 60/67] address comments --- .../drivers/vector-store-drivers.md | 2 +- ...ptape_cloud_knowledge_base_vector_store_driver.py | 12 +----------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 834f0ac72..a0ebe7fe7 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -51,7 +51,7 @@ 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 support, only querying. Here is a complete example of how the driver can be used to query an existing 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 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 0778d3d37..957edebb8 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,14 +1,6 @@ import pytest import uuid - - -class MockResponse: - def __init__(self, json_data, status_code): - self.json_data = json_data - self.status_code = status_code - - def json(self): - return self.json_data +from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: @@ -20,8 +12,6 @@ class TestGriptapeCloudKnowledgeBaseVectorStoreDriver: @pytest.fixture def driver(self, mocker): - from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver - test_entries = { "entries": [ { From b1b6c88557e1ece0fd235d27e315470b7e3a1bb8 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 10:30:13 -0700 Subject: [PATCH 61/67] Update doc formatting --- .../drivers/vector-store-drivers.md | 133 +++++++++++------- 1 file changed, 79 insertions(+), 54 deletions(-) diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index a0ebe7fe7..060317d0f 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,7 +8,7 @@ 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 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. @@ -20,7 +20,7 @@ Each vector driver takes a [BaseEmbeddingDriver](../../reference/griptape/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: +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( @@ -51,7 +54,7 @@ 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: +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 @@ -76,11 +79,11 @@ 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 @@ -109,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( @@ -132,25 +135,25 @@ result = vector_store_driver.query( ### 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 +# Initialize the Vector Store Driver vector_store_driver = MarqoVectorStoreDriver( api_key=os.environ["MARQO_API_KEY"], url=os.environ["MARQO_URL"], @@ -158,10 +161,10 @@ vector_store_driver = MarqoVectorStoreDriver( 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, @@ -169,24 +172,27 @@ vector_store_driver.upsert_text_artifacts( ) result = vector_store_driver.query(query="What is griptape?") -print(result) + +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"] @@ -197,7 +203,7 @@ 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 +# Initialize the Vector Store Driver vector_store_driver = MongoDbAtlasVectorStoreDriver( connection_string=f"mongodb+srv://{username}:{password}@{host}/{database_name}", database_name=database_name, @@ -207,10 +213,10 @@ vector_store_driver = 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 +# Upsert Artifacts into the Vector Store Driver vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, @@ -218,7 +224,10 @@ vector_store_driver.upsert_text_artifacts( ) result = vector_store_driver.query(query="What is griptape?") -print(result) + +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: @@ -243,18 +252,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"] @@ -265,7 +274,7 @@ 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 +# 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, @@ -275,10 +284,10 @@ vector_store_driver = 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 +# Upsert Artifacts into the Vector Store Driver vector_store_driver.upsert_text_artifacts( { "griptape": artifacts, @@ -286,17 +295,20 @@ vector_store_driver.upsert_text_artifacts( ) result = vector_store_driver.query(query="What is griptape?") -print(result) + +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 @@ -304,7 +316,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( @@ -315,10 +327,10 @@ 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, @@ -326,7 +338,10 @@ vector_store_driver.upsert_text_artifacts( ) result = vector_store_driver.query(query="What is griptape?") -print(result) + +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: @@ -337,11 +352,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 @@ -349,7 +364,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( @@ -359,10 +374,10 @@ 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, @@ -371,7 +386,9 @@ vector_store_driver.upsert_text_artifacts( result = vector_store_driver.query(query="What is griptape?") -print(result) +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` The body mappings for creating a vector index should look similar to the following: @@ -390,18 +407,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"] @@ -419,8 +436,10 @@ 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, @@ -428,17 +447,20 @@ vector_store_driver.upsert_text_artifacts( ) result = vector_store_driver.query(query="What is griptape?") -print(result) + +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 @@ -451,14 +473,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", @@ -467,7 +489,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 @@ -489,6 +511,9 @@ vector_store_driver.upsert_vector( content=artifacts[0].value ) -print("Vectors successfully inserted into Qdrant.") +result = vector_store_driver.query(query="What is griptape?") +values = [r.to_artifact().value for r in results] + +print("\n\n".join(values)) ``` From 6f27f3814204d889f3416730e494f26fddbaa936 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 10:33:37 -0700 Subject: [PATCH 62/67] another docs format --- docs/griptape-framework/drivers/vector-store-drivers.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 060317d0f..cb0c2d50e 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -8,13 +8,13 @@ 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. !!! info - More vector drivers are coming soon. + More Vector Store Drivers are coming soon. ## Vector Store Drivers From e7b30183c85698377934e486403020db4d99522f Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 10:35:25 -0700 Subject: [PATCH 63/67] another d to D --- docs/griptape-framework/drivers/vector-store-drivers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index cb0c2d50e..2e3504b87 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -11,7 +11,7 @@ Griptape provides a way to build drivers for vector DBs where embeddings can be 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 Store Drivers are coming soon. From dc0938b4ee59a26ae9486e1a033d86010136461f Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 11:07:59 -0700 Subject: [PATCH 64/67] single summary lines --- ...ptape_cloud_knowledge_base_vector_store_driver.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) 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 08a2a643a..d43e3340a 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 @@ -62,15 +62,11 @@ def load_entry(self, vector_id: str, namespace: Optional[str] = None) -> BaseVec raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") 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.""" raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: - """Retrieves all Artifacts from the collection, optionally filtering to only - those that match the provided namespace. - """ + """Retrieves all Artifacts from the collection, optionally filtering to only those that match the provided namespace.""" raise NotImplementedError(f"{self.__class__.__name__} does not support Artifact loading.") def query( @@ -84,9 +80,7 @@ def query( filter: Optional[dict] = None, **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: - """Performs a search on the Knowledge Base to find vectors similar to the provided input vector, - optionally filtering to only those that match the provided filter(s). - """ + """Performs a search on the Knowledge Base to find vectors similar to the provided input vector, 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] = { From d4860e67d58883d0e996550dd3d2c52e3b0388f9 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 11:11:49 -0700 Subject: [PATCH 65/67] back to multi-line with space --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) 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 d43e3340a..ae2f8dd8d 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 @@ -58,15 +58,12 @@ def upsert_text( raise NotImplementedError(f"{self.__class__.__name__} does not support text upsert.") 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.""" raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") 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.""" raise NotImplementedError(f"{self.__class__.__name__} does not support entry loading.") def load_artifacts(self, namespace: Optional[str] = None) -> ListArtifact: - """Retrieves all Artifacts from the collection, optionally filtering to only those that match the provided namespace.""" raise NotImplementedError(f"{self.__class__.__name__} does not support Artifact loading.") def query( @@ -80,7 +77,9 @@ def query( filter: Optional[dict] = None, **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: - """Performs a search on the Knowledge Base to find vectors similar to the provided input vector, optionally filtering to only those that match the provided filter(s).""" + """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] = { From 3bac8d18e61b4c0510776a98303c17152d8c68fe Mon Sep 17 00:00:00 2001 From: cjkindel Date: Thu, 11 Jul 2024 11:16:08 -0700 Subject: [PATCH 66/67] I want a single command to run all checks that isn't the pre-commit hook --- .../griptape_cloud_knowledge_base_vector_store_driver.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 ae2f8dd8d..0c7d5c961 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 @@ -77,9 +77,10 @@ def query( filter: Optional[dict] = None, **kwargs, ) -> list[BaseVectorStoreDriver.Entry]: - """Performs a query on the Knowledge Base + """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).""" + 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] = { From 3165299a8b01df3bf57445611fdc5a4252d2d086 Mon Sep 17 00:00:00 2001 From: cjkindel Date: Fri, 12 Jul 2024 08:36:16 -0700 Subject: [PATCH 67/67] doc integ test fix --- .../drivers/vector-store-drivers.md | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/docs/griptape-framework/drivers/vector-store-drivers.md b/docs/griptape-framework/drivers/vector-store-drivers.md index 2e3504b87..ea2b72a56 100644 --- a/docs/griptape-framework/drivers/vector-store-drivers.md +++ b/docs/griptape-framework/drivers/vector-store-drivers.md @@ -63,12 +63,12 @@ from griptape.drivers import GriptapeCloudKnowledgeBaseVectorStoreDriver # Initialize environment variables -gt_cloud_api_key = os.environ["GT_CLOUD_API_KEY"] -gt_cloud_knowledge_base_id = os.environ["GT_CLOUD_KNOWLEDGE_BASE_ID"] +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) -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] @@ -124,12 +124,16 @@ 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 @@ -171,7 +175,7 @@ vector_store_driver.upsert_text_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] @@ -223,7 +227,7 @@ vector_store_driver.upsert_text_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] @@ -294,7 +298,7 @@ vector_store_driver.upsert_text_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] @@ -337,7 +341,7 @@ vector_store_driver.upsert_text_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] @@ -384,7 +388,7 @@ vector_store_driver.upsert_text_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] @@ -446,7 +450,7 @@ vector_store_driver.upsert_text_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] @@ -511,7 +515,7 @@ vector_store_driver.upsert_vector( content=artifacts[0].value ) -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]