diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml index 79659073..6f4f3eee 100644 --- a/.code-samples.meilisearch.yaml +++ b/.code-samples.meilisearch.yaml @@ -565,6 +565,18 @@ update_prefix_search_settings_1: |- client.index('books').update_prefix_search(PrefixSearch.DISABLED) reset_prefix_search_settings_1: |- client.index('books').reset_prefix_search() +get_chat_settings_1: |- + client.index('books').get_chat_settings() +update_chat_settings_1: |- + client.update_experimental_features({'chatCompletions': True}) + client.index('books').update_chat_settings({ + 'description': 'A collection of books with titles, authors and genres', + 'documentTemplate': 'A book titled {{ doc.title }} by {{ doc.author }}', + 'documentTemplateMaxBytes': 400, + 'searchParameters': {'limit': 5} + }) +reset_chat_settings_1: |- + client.index('books').reset_chat_settings() get_proximity_precision_settings_1: |- client.index('books').get_proximity_precision() update_proximity_precision_settings_1: |- diff --git a/meilisearch/config.py b/meilisearch/config.py index 993d7d38..2b35da66 100644 --- a/meilisearch/config.py +++ b/meilisearch/config.py @@ -42,6 +42,7 @@ class Paths: embedders = "embedders" search_cutoff_ms = "search-cutoff-ms" prefix_search = "prefix-search" + chat = "chat" proximity_precision = "proximity-precision" localized_attributes = "localized-attributes" fields = "fields" diff --git a/meilisearch/index.py b/meilisearch/index.py index 82a74fed..c459cfcc 100644 --- a/meilisearch/index.py +++ b/meilisearch/index.py @@ -2515,6 +2515,73 @@ def reset_prefix_search(self) -> TaskInfo: return TaskInfo(**task) + # CHAT SETTINGS + + def get_chat_settings(self) -> dict[str, Any]: + """Get the chat settings of an index. + + These settings describe the index to the LLM used by conversational search. + https://www.meilisearch.com/docs/reference/api/settings/get-chat + + Returns + ------- + settings: + Dictionary containing the chat settings of the index. + + Raises + ------ + MeilisearchApiError + An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors + """ + return self.http.get(self.__settings_url_for(self.config.paths.chat)) + + def update_chat_settings(self, body: Mapping[str, Any]) -> TaskInfo: + """Update the chat settings of the index. + + Updating chat settings requires the `chatCompletions` experimental feature. + https://www.meilisearch.com/docs/reference/api/settings/update-chat + + Parameters + ---------- + body: + Dictionary containing the chat settings, for example `description`, + `documentTemplate`, `documentTemplateMaxBytes` and `searchParameters`. + + Returns + ------- + task_info: + TaskInfo instance containing information about a task to track the progress of an asynchronous process. + https://www.meilisearch.com/docs/reference/api/tasks#get-one-task + + Raises + ------ + MeilisearchApiError + An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors + """ + task = self.http.patch(path=self.__settings_url_for(self.config.paths.chat), body=body) + + return TaskInfo(**task) + + def reset_chat_settings(self) -> TaskInfo: + """Reset the chat settings of the index to default values. + + https://www.meilisearch.com/docs/reference/api/settings/reset-chat + + Returns + ------- + task_info: + TaskInfo instance containing information about a task to track the progress of an asynchronous process. + https://www.meilisearch.com/docs/reference/api/tasks#get-one-task + + Raises + ------ + MeilisearchApiError + An error containing details about why Meilisearch can't process your request. Meilisearch error codes are described here: https://www.meilisearch.com/docs/reference/errors/error_codes#meilisearch-errors + """ + task = self.http.delete(self.__settings_url_for(self.config.paths.chat)) + + return TaskInfo(**task) + # PROXIMITY PRECISION SETTINGS def get_proximity_precision(self) -> ProximityPrecision: diff --git a/tests/settings/test_settings_chat_meilisearch.py b/tests/settings/test_settings_chat_meilisearch.py new file mode 100644 index 00000000..a754d5fd --- /dev/null +++ b/tests/settings/test_settings_chat_meilisearch.py @@ -0,0 +1,68 @@ +import pytest + +DEFAULT_CHAT_SETTINGS_KEYS = { + "description", + "documentTemplate", + "documentTemplateMaxBytes", + "searchParameters", +} + +NEW_CHAT_SETTINGS = { + "description": "A collection of movies", + "documentTemplate": "A movie titled {{ doc.title }}", + "documentTemplateMaxBytes": 200, + "searchParameters": {"limit": 5}, +} + + +@pytest.fixture +def chat_completions_enabled(client): + """Updating index chat settings requires the chatCompletions experimental feature.""" + previous = client.get_experimental_features().get("chatCompletions", False) + client.update_experimental_features({"chatCompletions": True}) + yield + client.update_experimental_features({"chatCompletions": previous}) + + +def test_get_chat_settings(empty_index): + response = empty_index().get_chat_settings() + + assert DEFAULT_CHAT_SETTINGS_KEYS == set(response) + assert response["description"] == "" + assert response["documentTemplateMaxBytes"] == 400 + assert response["searchParameters"] == {} + + +def test_update_chat_settings(empty_index, chat_completions_enabled): + index = empty_index() + + response = index.update_chat_settings(NEW_CHAT_SETTINGS) + index.wait_for_task(response.task_uid) + response = index.get_chat_settings() + + assert response == NEW_CHAT_SETTINGS + + +def test_update_chat_settings_partial(empty_index, chat_completions_enabled): + index = empty_index() + index.wait_for_task(index.update_chat_settings(NEW_CHAT_SETTINGS).task_uid) + + response = index.update_chat_settings({"description": "Updated"}) + index.wait_for_task(response.task_uid) + response = index.get_chat_settings() + + assert response["description"] == "Updated" + assert response["documentTemplate"] == NEW_CHAT_SETTINGS["documentTemplate"] + assert response["searchParameters"] == NEW_CHAT_SETTINGS["searchParameters"] + + +def test_reset_chat_settings(empty_index, chat_completions_enabled): + index = empty_index() + default_settings = index.get_chat_settings() + index.wait_for_task(index.update_chat_settings(NEW_CHAT_SETTINGS).task_uid) + assert index.get_chat_settings() != default_settings + + response = index.reset_chat_settings() + index.wait_for_task(response.task_uid) + + assert index.get_chat_settings() == default_settings