From a54dde05093649a48fb09227520fb33c8cb0796d Mon Sep 17 00:00:00 2001 From: Deshraj Yadav Date: Sat, 30 Dec 2023 15:36:24 +0530 Subject: [PATCH] [Bug Fix] Handle chat sessions properly during `app.chat()` calls (#1084) --- embedchain/embedchain.py | 25 ++++--- embedchain/llm/base.py | 27 ++++--- embedchain/memory/base.py | 85 ++++++++++++---------- embedchain/memory/message.py | 14 ++-- poetry.lock | 103 +++------------------------ pyproject.toml | 2 +- tests/embedchain/test_embedchain.py | 6 +- tests/llm/test_chat.py | 10 +-- tests/memory/test_chat_memory.py | 27 +++---- tests/memory/test_memory_messages.py | 12 ++-- 10 files changed, 124 insertions(+), 187 deletions(-) diff --git a/embedchain/embedchain.py b/embedchain/embedchain.py index 741cbd24..79b0a371 100644 --- a/embedchain/embedchain.py +++ b/embedchain/embedchain.py @@ -7,9 +7,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union from dotenv import load_dotenv from langchain.docstore.document import Document -from embedchain.cache import (adapt, get_gptcache_session, - gptcache_data_convert, - gptcache_update_cache_callback) +from embedchain.cache import adapt, get_gptcache_session, gptcache_data_convert, gptcache_update_cache_callback from embedchain.chunkers.base_chunker import BaseChunker from embedchain.config import AddConfig, BaseLlmConfig, ChunkerConfig from embedchain.config.base_app_config import BaseAppConfig @@ -19,8 +17,7 @@ from embedchain.embedder.base import BaseEmbedder from embedchain.helpers.json_serializable import JSONSerializable from embedchain.llm.base import BaseLlm from embedchain.loaders.base_loader import BaseLoader -from embedchain.models.data_type import (DataType, DirectDataType, - IndirectDataType, SpecialDataType) +from embedchain.models.data_type import DataType, DirectDataType, IndirectDataType, SpecialDataType from embedchain.telemetry.posthog import AnonymousTelemetry from embedchain.utils import detect_datatype, is_valid_json_string from embedchain.vectordb.base import BaseVectorDB @@ -580,6 +577,7 @@ class EmbedChain(JSONSerializable): input_query: str, config: Optional[BaseLlmConfig] = None, dry_run=False, + session_id: str = "default", where: Optional[Dict[str, str]] = None, citations: bool = False, **kwargs: Dict[str, Any], @@ -599,6 +597,8 @@ class EmbedChain(JSONSerializable): :param dry_run: A dry run does everything except send the resulting prompt to the LLM. The purpose is to test the prompt, not the response., defaults to False :type dry_run: bool, optional + :param session_id: The session id to use for chat history, defaults to 'default'. + :type session_id: Optional[str], optional :param where: A dictionary of key-value pairs to filter the database results., defaults to None :type where: Optional[Dict[str, str]], optional :param kwargs: To read more params for the query function. Ex. we use citations boolean @@ -616,6 +616,9 @@ class EmbedChain(JSONSerializable): else: contexts_data_for_llm_query = contexts + # Update the history beforehand so that we can handle multiple chat sessions in the same python session + self.llm.update_history(app_id=self.config.id, session_id=session_id) + if self.cache_config is not None: logging.info("Cache enabled. Checking cache...") answer = adapt( @@ -634,7 +637,7 @@ class EmbedChain(JSONSerializable): ) # add conversation in memory - self.llm.add_history(self.config.id, input_query, answer) + self.llm.add_history(self.config.id, input_query, answer, session_id=session_id) # Send anonymous telemetry self.telemetry.capture(event_name="chat", properties=self._telemetry_props) @@ -684,12 +687,8 @@ class EmbedChain(JSONSerializable): self.telemetry.capture(event_name="reset", properties=self._telemetry_props) def get_history(self, num_rounds: int = 10, display_format: bool = True): - return self.llm.memory.get_recent_memories( - app_id=self.config.id, - num_rounds=num_rounds, - display_format=display_format, - ) + return self.llm.memory.get(app_id=self.config.id, num_rounds=num_rounds, display_format=display_format) - def delete_chat_history(self): - self.llm.memory.delete_chat_history(app_id=self.config.id) + def delete_chat_history(self, session_id: str = "default"): + self.llm.memory.delete(app_id=self.config.id, session_id=session_id) self.llm.update_history(app_id=self.config.id) diff --git a/embedchain/llm/base.py b/embedchain/llm/base.py index ff2d5d17..2fe345af 100644 --- a/embedchain/llm/base.py +++ b/embedchain/llm/base.py @@ -8,7 +8,7 @@ from embedchain.config.llm.base import (DEFAULT_PROMPT, DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE, DOCS_SITE_PROMPT_TEMPLATE) from embedchain.helpers.json_serializable import JSONSerializable -from embedchain.memory.base import ECChatMemory +from embedchain.memory.base import ChatHistory from embedchain.memory.message import ChatMessage @@ -24,7 +24,7 @@ class BaseLlm(JSONSerializable): else: self.config = config - self.memory = ECChatMemory() + self.memory = ChatHistory() self.is_docs_site_instance = False self.online = False self.history: Any = None @@ -45,17 +45,24 @@ class BaseLlm(JSONSerializable): """ self.history = history - def update_history(self, app_id: str): + def update_history(self, app_id: str, session_id: str = "default"): """Update class history attribute with history in memory (for chat method)""" - chat_history = self.memory.get_recent_memories(app_id=app_id, num_rounds=10) + chat_history = self.memory.get(app_id=app_id, session_id=session_id, num_rounds=10) self.set_history([str(history) for history in chat_history]) - def add_history(self, app_id: str, question: str, answer: str, metadata: Optional[Dict[str, Any]] = None): + def add_history( + self, + app_id: str, + question: str, + answer: str, + metadata: Optional[Dict[str, Any]] = None, + session_id: str = "default", + ): chat_message = ChatMessage() chat_message.add_user_message(question, metadata=metadata) chat_message.add_ai_message(answer, metadata=metadata) - self.memory.add(app_id=app_id, chat_message=chat_message) - self.update_history(app_id=app_id) + self.memory.add(app_id=app_id, chat_message=chat_message, session_id=session_id) + self.update_history(app_id=app_id, session_id=session_id) def generate_prompt(self, input_query: str, contexts: List[str], **kwargs: Dict[str, Any]) -> str: """ @@ -212,7 +219,9 @@ class BaseLlm(JSONSerializable): # Restore previous config self.config: BaseLlmConfig = BaseLlmConfig.deserialize(prev_config) - def chat(self, input_query: str, contexts: List[str], config: BaseLlmConfig = None, dry_run=False): + def chat( + self, input_query: str, contexts: List[str], config: BaseLlmConfig = None, dry_run=False, session_id: str = None + ): """ Queries the vector database on the given input query. Gets relevant doc based on the query and then passes it to an @@ -230,6 +239,8 @@ class BaseLlm(JSONSerializable): :param dry_run: A dry run does everything except send the resulting prompt to the LLM. The purpose is to test the prompt, not the response., defaults to False :type dry_run: bool, optional + :param session_id: Session ID to use for the conversation, defaults to None + :type session_id: str, optional :return: The answer to the query or the dry run result :rtype: str """ diff --git a/embedchain/memory/base.py b/embedchain/memory/base.py index d80cf779..dda7c29c 100644 --- a/embedchain/memory/base.py +++ b/embedchain/memory/base.py @@ -9,40 +9,41 @@ from embedchain.memory.message import ChatMessage from embedchain.memory.utils import merge_metadata_dict CHAT_MESSAGE_CREATE_TABLE_QUERY = """ - CREATE TABLE IF NOT EXISTS chat_history ( - app_id TEXT, - id TEXT, - question TEXT, - answer TEXT, - metadata TEXT, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (id, app_id) - ) - """ + CREATE TABLE IF NOT EXISTS ec_chat_history ( + app_id TEXT, + id TEXT, + session_id TEXT, + question TEXT, + answer TEXT, + metadata TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id, app_id, session_id) + ) +""" -class ECChatMemory: +class ChatHistory: def __init__(self) -> None: with sqlite3.connect(SQLITE_PATH, check_same_thread=False) as self.connection: self.cursor = self.connection.cursor() - self.cursor.execute(CHAT_MESSAGE_CREATE_TABLE_QUERY) self.connection.commit() - def add(self, app_id, chat_message: ChatMessage) -> Optional[str]: + def add(self, app_id, session_id, chat_message: ChatMessage) -> Optional[str]: memory_id = str(uuid.uuid4()) metadata_dict = merge_metadata_dict(chat_message.human_message.metadata, chat_message.ai_message.metadata) if metadata_dict: metadata = self._serialize_json(metadata_dict) ADD_CHAT_MESSAGE_QUERY = """ - INSERT INTO chat_history (app_id, id, question, answer, metadata) - VALUES (?, ?, ?, ?, ?) + INSERT INTO ec_chat_history (app_id, id, session_id, question, answer, metadata) + VALUES (?, ?, ?, ?, ?, ?) """ self.cursor.execute( ADD_CHAT_MESSAGE_QUERY, ( app_id, memory_id, + session_id, chat_message.human_message.content, chat_message.ai_message.content, metadata if metadata_dict else "{}", @@ -52,37 +53,41 @@ class ECChatMemory: logging.info(f"Added chat memory to db with id: {memory_id}") return memory_id - def delete_chat_history(self, app_id: str): - DELETE_CHAT_HISTORY_QUERY = """ - DELETE FROM chat_history WHERE app_id=? + def delete(self, app_id: str, session_id: str): """ - self.cursor.execute( - DELETE_CHAT_HISTORY_QUERY, - (app_id,), - ) + Delete all chat history for a given app_id and session_id. + This is useful for deleting chat history for a given user. + + :param app_id: The app_id to delete chat history for + :param session_id: The session_id to delete chat history for + + :return: None + """ + DELETE_CHAT_HISTORY_QUERY = "DELETE FROM ec_chat_history WHERE app_id=? AND session_id=?" + self.cursor.execute(DELETE_CHAT_HISTORY_QUERY, (app_id, session_id)) self.connection.commit() - def get_recent_memories(self, app_id, num_rounds=10, display_format=False) -> List[ChatMessage]: + def get(self, app_id, session_id, num_rounds=10, display_format=False) -> List[ChatMessage]: """ Get the most recent num_rounds rounds of conversations between human and AI, for a given app_id. """ QUERY = """ - SELECT * FROM chat_history - WHERE app_id=? + SELECT * FROM ec_chat_history + WHERE app_id=? AND session_id=? ORDER BY created_at DESC LIMIT ? """ self.cursor.execute( QUERY, - (app_id, num_rounds), + (app_id, session_id, num_rounds), ) results = self.cursor.fetchall() history = [] for result in results: - app_id, _, question, answer, metadata, timestamp = result + app_id, _, session_id, question, answer, metadata, timestamp = result metadata = self._deserialize_json(metadata=metadata) # Return list of dict if display_format is True if display_format: @@ -94,6 +99,20 @@ class ECChatMemory: history.append(memory) return history + def count(self, app_id: str, session_id: str): + """ + Count the number of chat messages for a given app_id and session_id. + + :param app_id: The app_id to count chat history for + :param session_id: The session_id to count chat history for + + :return: The number of chat messages for a given app_id and session_id + """ + QUERY = "SELECT COUNT(*) FROM ec_chat_history WHERE app_id=? AND session_id=?" + self.cursor.execute(QUERY, (app_id, session_id)) + count = self.cursor.fetchone()[0] + return count + def _serialize_json(self, metadata: Dict[str, Any]): return json.dumps(metadata) @@ -102,15 +121,3 @@ class ECChatMemory: def close_connection(self): self.connection.close() - - def count_history_messages(self, app_id: str): - QUERY = """ - SELECT COUNT(*) FROM chat_history - WHERE app_id=? - """ - self.cursor.execute( - QUERY, - (app_id,), - ) - count = self.cursor.fetchone()[0] - return count diff --git a/embedchain/memory/message.py b/embedchain/memory/message.py index 99081d2d..7e5c7b86 100644 --- a/embedchain/memory/message.py +++ b/embedchain/memory/message.py @@ -14,16 +14,16 @@ class BaseMessage(JSONSerializable): # The string content of the message. content: str - # The creator of the message. AI, Human, Bot etc. - by: str + # The created_by of the message. AI, Human, Bot etc. + created_by: str # Any additional info. metadata: Dict[str, Any] - def __init__(self, content: str, creator: str, metadata: Optional[Dict[str, Any]] = None) -> None: + def __init__(self, content: str, created_by: str, metadata: Optional[Dict[str, Any]] = None) -> None: super().__init__() self.content = content - self.creator = creator + self.created_by = created_by self.metadata = metadata @property @@ -36,7 +36,7 @@ class BaseMessage(JSONSerializable): return True def __str__(self) -> str: - return f"{self.creator}: {self.content}" + return f"{self.created_by}: {self.content}" class ChatMessage(JSONSerializable): @@ -57,7 +57,7 @@ class ChatMessage(JSONSerializable): overwritting it with new message." ) - self.human_message = BaseMessage(content=message, creator="human", metadata=metadata) + self.human_message = BaseMessage(content=message, created_by="human", metadata=metadata) def add_ai_message(self, message: str, metadata: Optional[dict] = None): if self.ai_message: @@ -66,7 +66,7 @@ class ChatMessage(JSONSerializable): overwritting it with new message." ) - self.ai_message = BaseMessage(content=message, creator="ai", metadata=metadata) + self.ai_message = BaseMessage(content=message, created_by="ai", metadata=metadata) def __str__(self) -> str: return f"{self.human_message}\n{self.ai_message}" diff --git a/poetry.lock b/poetry.lock index ff2091c0..0bd5edaf 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. [[package]] name = "aiofiles" @@ -354,26 +354,6 @@ description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, - {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, - {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, - {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, - {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, - {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, - {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, - {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, - {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, - {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, - {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, - {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, - {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, - {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, ] @@ -2218,7 +2198,7 @@ files = [ {file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0b72b802496cccbd9b31acea72b6f87e7771ccfd7f7927437d592e5c92ed703c"}, {file = "greenlet-3.0.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:527cd90ba3d8d7ae7dceb06fda619895768a46a1b4e423bdb24c1969823b8362"}, {file = "greenlet-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:37f60b3a42d8b5499be910d1267b24355c495064f271cfe74bf28b17b099133c"}, - {file = "greenlet-3.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:1482fba7fbed96ea7842b5a7fc11d61727e8be75a077e603e8ab49d24e234383"}, + {file = "greenlet-3.0.0-cp311-universal2-macosx_10_9_universal2.whl", hash = "sha256:c3692ecf3fe754c8c0f2c95ff19626584459eab110eaab66413b1e7425cd84e9"}, {file = "greenlet-3.0.0-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:be557119bf467d37a8099d91fbf11b2de5eb1fd5fc5b91598407574848dc910f"}, {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04"}, {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2"}, @@ -2228,6 +2208,7 @@ files = [ {file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:952256c2bc5b4ee8df8dfc54fc4de330970bf5d79253c863fb5e6761f00dda35"}, {file = "greenlet-3.0.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:269d06fa0f9624455ce08ae0179430eea61085e3cf6457f05982b37fd2cefe17"}, {file = "greenlet-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9adbd8ecf097e34ada8efde9b6fec4dd2a903b1e98037adf72d12993a1c80b51"}, + {file = "greenlet-3.0.0-cp312-universal2-macosx_10_9_universal2.whl", hash = "sha256:553d6fb2324e7f4f0899e5ad2c427a4579ed4873f42124beba763f16032959af"}, {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6b5ce7f40f0e2f8b88c28e6691ca6806814157ff05e794cdd161be928550f4c"}, {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810"}, {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7"}, @@ -3339,16 +3320,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -4198,10 +4169,12 @@ files = [ [package.dependencies] numpy = [ - {version = ">=1.21.0", markers = "python_version == \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""}, - {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\" and python_version < \"3.11\""}, - {version = ">=1.21.2", markers = "platform_system != \"Darwin\" and python_version >= \"3.10\" and python_version < \"3.11\""}, - {version = ">=1.19.3", markers = "platform_system == \"Linux\" and platform_machine == \"aarch64\" and python_version >= \"3.8\" and python_version < \"3.10\" or python_version > \"3.9\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_system != \"Darwin\" and python_version < \"3.10\" or python_version >= \"3.9\" and platform_machine != \"arm64\" and python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version <= \"3.9\" and platform_system == \"Darwin\" and platform_machine == \"arm64\""}, + {version = ">=1.21.2", markers = "python_version >= \"3.10\""}, + {version = ">=1.21.4", markers = "python_version >= \"3.10\" and platform_system == \"Darwin\""}, + {version = ">=1.19.3", markers = "python_version >= \"3.6\" and platform_system == \"Linux\" and platform_machine == \"aarch64\" or python_version >= \"3.9\""}, + {version = ">=1.17.0", markers = "python_version >= \"3.7\""}, + {version = ">=1.17.3", markers = "python_version >= \"3.8\""}, {version = ">=1.23.5", markers = "python_version >= \"3.11\""}, ] @@ -5598,7 +5571,6 @@ files = [ {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"}, {file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"}, - {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"}, {file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"}, {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"}, {file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"}, @@ -5606,15 +5578,8 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"}, {file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"}, - {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"}, {file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"}, {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, - {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, - {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, - {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, - {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"}, {file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"}, {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"}, @@ -5631,7 +5596,6 @@ files = [ {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"}, {file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"}, - {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"}, {file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"}, {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"}, {file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"}, @@ -5639,7 +5603,6 @@ files = [ {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"}, {file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"}, - {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"}, {file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"}, {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"}, {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, @@ -6200,11 +6163,6 @@ files = [ {file = "scikit_learn-1.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f66eddfda9d45dd6cadcd706b65669ce1df84b8549875691b1f403730bdef217"}, {file = "scikit_learn-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6448c37741145b241eeac617028ba6ec2119e1339b1385c9720dae31367f2be"}, {file = "scikit_learn-1.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:c413c2c850241998168bbb3bd1bb59ff03b1195a53864f0b80ab092071af6028"}, - {file = "scikit_learn-1.3.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ef540e09873e31569bc8b02c8a9f745ee04d8e1263255a15c9969f6f5caa627f"}, - {file = "scikit_learn-1.3.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:9147a3a4df4d401e618713880be023e36109c85d8569b3bf5377e6cd3fecdeac"}, - {file = "scikit_learn-1.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2cd3634695ad192bf71645702b3df498bd1e246fc2d529effdb45a06ab028b4"}, - {file = "scikit_learn-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c275a06c5190c5ce00af0acbb61c06374087949f643ef32d355ece12c4db043"}, - {file = "scikit_learn-1.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:0e1aa8f206d0de814b81b41d60c1ce31f7f2c7354597af38fae46d9c47c45122"}, {file = "scikit_learn-1.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:52b77cc08bd555969ec5150788ed50276f5ef83abb72e6f469c5b91a0009bbca"}, {file = "scikit_learn-1.3.1-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a683394bc3f80b7c312c27f9b14ebea7766b1f0a34faf1a2e9158d80e860ec26"}, {file = "scikit_learn-1.3.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a15d964d9eb181c79c190d3dbc2fff7338786bf017e9039571418a1d53dab236"}, @@ -6547,54 +6505,13 @@ description = "Database Abstraction Library" optional = false python-versions = ">=3.7" files = [ - {file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f146c61ae128ab43ea3a0955de1af7e1633942c2b2b4985ac51cc292daf33222"}, - {file = "SQLAlchemy-2.0.22-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:875de9414393e778b655a3d97d60465eb3fae7c919e88b70cc10b40b9f56042d"}, - {file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13790cb42f917c45c9c850b39b9941539ca8ee7917dacf099cc0b569f3d40da7"}, - {file = "SQLAlchemy-2.0.22-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e04ab55cf49daf1aeb8c622c54d23fa4bec91cb051a43cc24351ba97e1dd09f5"}, - {file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a42c9fa3abcda0dcfad053e49c4f752eef71ecd8c155221e18b99d4224621176"}, - {file = "SQLAlchemy-2.0.22-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:14cd3bcbb853379fef2cd01e7c64a5d6f1d005406d877ed9509afb7a05ff40a5"}, - {file = "SQLAlchemy-2.0.22-cp310-cp310-win32.whl", hash = "sha256:d143c5a9dada696bcfdb96ba2de4a47d5a89168e71d05a076e88a01386872f97"}, - {file = "SQLAlchemy-2.0.22-cp310-cp310-win_amd64.whl", hash = "sha256:ccd87c25e4c8559e1b918d46b4fa90b37f459c9b4566f1dfbce0eb8122571547"}, {file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4f6ff392b27a743c1ad346d215655503cec64405d3b694228b3454878bf21590"}, {file = "SQLAlchemy-2.0.22-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f776c2c30f0e5f4db45c3ee11a5f2a8d9de68e81eb73ec4237de1e32e04ae81c"}, - {file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8f1792d20d2f4e875ce7a113f43c3561ad12b34ff796b84002a256f37ce9437"}, - {file = "SQLAlchemy-2.0.22-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d80eeb5189d7d4b1af519fc3f148fe7521b9dfce8f4d6a0820e8f5769b005051"}, - {file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:69fd9e41cf9368afa034e1c81f3570afb96f30fcd2eb1ef29cb4d9371c6eece2"}, - {file = "SQLAlchemy-2.0.22-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54bcceaf4eebef07dadfde424f5c26b491e4a64e61761dea9459103ecd6ccc95"}, - {file = "SQLAlchemy-2.0.22-cp311-cp311-win32.whl", hash = "sha256:7ee7ccf47aa503033b6afd57efbac6b9e05180f492aeed9fcf70752556f95624"}, - {file = "SQLAlchemy-2.0.22-cp311-cp311-win_amd64.whl", hash = "sha256:b560f075c151900587ade06706b0c51d04b3277c111151997ea0813455378ae0"}, {file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:2c9bac865ee06d27a1533471405ad240a6f5d83195eca481f9fc4a71d8b87df8"}, {file = "SQLAlchemy-2.0.22-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:625b72d77ac8ac23da3b1622e2da88c4aedaee14df47c8432bf8f6495e655de2"}, - {file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b39a6e21110204a8c08d40ff56a73ba542ec60bab701c36ce721e7990df49fb9"}, - {file = "SQLAlchemy-2.0.22-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53a766cb0b468223cafdf63e2d37f14a4757476157927b09300c8c5832d88560"}, - {file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0e1ce8ebd2e040357dde01a3fb7d30d9b5736b3e54a94002641dfd0aa12ae6ce"}, - {file = "SQLAlchemy-2.0.22-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:505f503763a767556fa4deae5194b2be056b64ecca72ac65224381a0acab7ebe"}, - {file = "SQLAlchemy-2.0.22-cp312-cp312-win32.whl", hash = "sha256:154a32f3c7b00de3d090bc60ec8006a78149e221f1182e3edcf0376016be9396"}, - {file = "SQLAlchemy-2.0.22-cp312-cp312-win_amd64.whl", hash = "sha256:129415f89744b05741c6f0b04a84525f37fbabe5dc3774f7edf100e7458c48cd"}, {file = "SQLAlchemy-2.0.22-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3940677d341f2b685a999bffe7078697b5848a40b5f6952794ffcf3af150c301"}, - {file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55914d45a631b81a8a2cb1a54f03eea265cf1783241ac55396ec6d735be14883"}, - {file = "SQLAlchemy-2.0.22-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2096d6b018d242a2bcc9e451618166f860bb0304f590d205173d317b69986c95"}, - {file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:19c6986cf2fb4bc8e0e846f97f4135a8e753b57d2aaaa87c50f9acbe606bd1db"}, - {file = "SQLAlchemy-2.0.22-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6ac28bd6888fe3c81fbe97584eb0b96804bd7032d6100b9701255d9441373ec1"}, - {file = "SQLAlchemy-2.0.22-cp37-cp37m-win32.whl", hash = "sha256:cb9a758ad973e795267da334a92dd82bb7555cb36a0960dcabcf724d26299db8"}, - {file = "SQLAlchemy-2.0.22-cp37-cp37m-win_amd64.whl", hash = "sha256:40b1206a0d923e73aa54f0a6bd61419a96b914f1cd19900b6c8226899d9742ad"}, {file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3aa1472bf44f61dd27987cd051f1c893b7d3b17238bff8c23fceaef4f1133868"}, {file = "SQLAlchemy-2.0.22-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:56a7e2bb639df9263bf6418231bc2a92a773f57886d371ddb7a869a24919face"}, - {file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ccca778c0737a773a1ad86b68bda52a71ad5950b25e120b6eb1330f0df54c3d0"}, - {file = "SQLAlchemy-2.0.22-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6c3e9350f9fb16de5b5e5fbf17b578811a52d71bb784cc5ff71acb7de2a7f9"}, - {file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:564e9f9e4e6466273dbfab0e0a2e5fe819eec480c57b53a2cdee8e4fdae3ad5f"}, - {file = "SQLAlchemy-2.0.22-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:af66001d7b76a3fab0d5e4c1ec9339ac45748bc4a399cbc2baa48c1980d3c1f4"}, - {file = "SQLAlchemy-2.0.22-cp38-cp38-win32.whl", hash = "sha256:9e55dff5ec115316dd7a083cdc1a52de63693695aecf72bc53a8e1468ce429e5"}, - {file = "SQLAlchemy-2.0.22-cp38-cp38-win_amd64.whl", hash = "sha256:4e869a8ff7ee7a833b74868a0887e8462445ec462432d8cbeff5e85f475186da"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9886a72c8e6371280cb247c5d32c9c8fa141dc560124348762db8a8b236f8692"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a571bc8ac092a3175a1d994794a8e7a1f2f651e7c744de24a19b4f740fe95034"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8db5ba8b7da759b727faebc4289a9e6a51edadc7fc32207a30f7c6203a181592"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0b3f2686c3f162123adba3cb8b626ed7e9b8433ab528e36ed270b4f70d1cdb"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0c1fea8c0abcb070ffe15311853abfda4e55bf7dc1d4889497b3403629f3bf00"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4bb062784f37b2d75fd9b074c8ec360ad5df71f933f927e9e95c50eb8e05323c"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-win32.whl", hash = "sha256:58a3aba1bfb32ae7af68da3f277ed91d9f57620cf7ce651db96636790a78b736"}, - {file = "SQLAlchemy-2.0.22-cp39-cp39-win_amd64.whl", hash = "sha256:92e512a6af769e4725fa5b25981ba790335d42c5977e94ded07db7d641490a85"}, - {file = "SQLAlchemy-2.0.22-py3-none-any.whl", hash = "sha256:3076740335e4aaadd7deb3fe6dcb96b3015f1613bd190a4e1634e1b99b02ec86"}, {file = "SQLAlchemy-2.0.22.tar.gz", hash = "sha256:5434cc601aa17570d79e5377f5fd45ff92f9379e2abed0be5e8c2fba8d353d2b"}, ] @@ -8205,4 +8122,4 @@ youtube = ["youtube-transcript-api", "yt_dlp"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "335c42c91a2b5e4a1c3d8a7c39dee8665fd1eee0410e1bc6cb6cb1d6f6722445" +content-hash = "2d59f37483caac14b4c0e10331facdab174deba143480df53340756330214010" diff --git a/pyproject.toml b/pyproject.toml index b26b8bcb..f1ff1dbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "embedchain" -version = "0.1.48" +version = "0.1.49" description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data" authors = [ "Taranjeet Singh ", diff --git a/tests/embedchain/test_embedchain.py b/tests/embedchain/test_embedchain.py index c1aca3d7..fb4ea402 100644 --- a/tests/embedchain/test_embedchain.py +++ b/tests/embedchain/test_embedchain.py @@ -7,7 +7,7 @@ from embedchain import App from embedchain.config import AppConfig, ChromaDbConfig from embedchain.embedchain import EmbedChain from embedchain.llm.base import BaseLlm -from embedchain.memory.base import ECChatMemory +from embedchain.memory.base import ChatHistory from embedchain.vectordb.chroma import ChromaDB os.environ["OPENAI_API_KEY"] = "test-api-key" @@ -31,7 +31,7 @@ def test_whole_app(app_instance, mocker): BaseLlm, "add_history", ) - mocker.patch.object(ECChatMemory, "delete_chat_history", autospec=True) + mocker.patch.object(ChatHistory, "delete", autospec=True) app_instance.add(knowledge, data_type="text") app_instance.query("What text did I give you?") @@ -50,7 +50,7 @@ def test_add_after_reset(app_instance, mocker): app_instance = App(config=config, db=db) # mock delete chat history - mocker.patch.object(ECChatMemory, "delete_chat_history", autospec=True) + mocker.patch.object(ChatHistory, "delete", autospec=True) app_instance.reset() diff --git a/tests/llm/test_chat.py b/tests/llm/test_chat.py index 16acef74..852b0b77 100644 --- a/tests/llm/test_chat.py +++ b/tests/llm/test_chat.py @@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch from embedchain import App from embedchain.config import AppConfig, BaseLlmConfig from embedchain.llm.base import BaseLlm -from embedchain.memory.base import ECChatMemory +from embedchain.memory.base import ChatHistory from embedchain.memory.message import ChatMessage @@ -36,11 +36,11 @@ class TestApp(unittest.TestCase): with patch.object(BaseLlm, "add_history") as mock_history: first_answer = app.chat("Test query 1") self.assertEqual(first_answer, "Test answer") - mock_history.assert_called_with(app.config.id, "Test query 1", "Test answer") + mock_history.assert_called_with(app.config.id, "Test query 1", "Test answer", session_id="default") - second_answer = app.chat("Test query 2") + second_answer = app.chat("Test query 2", session_id="test_session") self.assertEqual(second_answer, "Test answer") - mock_history.assert_called_with(app.config.id, "Test query 2", "Test answer") + mock_history.assert_called_with(app.config.id, "Test query 2", "Test answer", session_id="test_session") @patch.object(App, "_retrieve_from_database", return_value=["Test context"]) @patch.object(BaseLlm, "get_answer_from_llm", return_value="Test answer") @@ -51,7 +51,7 @@ class TestApp(unittest.TestCase): Also tests that a dry run does not change the history """ - with patch.object(ECChatMemory, "get_recent_memories") as mock_memory: + with patch.object(ChatHistory, "get") as mock_memory: mock_message = ChatMessage() mock_message.add_user_message("Test query 1") mock_message.add_ai_message("Test answer") diff --git a/tests/memory/test_chat_memory.py b/tests/memory/test_chat_memory.py index 9b78d200..d41bfbd1 100644 --- a/tests/memory/test_chat_memory.py +++ b/tests/memory/test_chat_memory.py @@ -1,17 +1,18 @@ import pytest -from embedchain.memory.base import ECChatMemory +from embedchain.memory.base import ChatHistory from embedchain.memory.message import ChatMessage -# Fixture for creating an instance of ECChatMemory +# Fixture for creating an instance of ChatHistory @pytest.fixture def chat_memory_instance(): - return ECChatMemory() + return ChatHistory() def test_add_chat_memory(chat_memory_instance): app_id = "test_app" + session_id = "test_session" human_message = "Hello, how are you?" ai_message = "I'm fine, thank you!" @@ -19,14 +20,15 @@ def test_add_chat_memory(chat_memory_instance): chat_message.add_user_message(human_message) chat_message.add_ai_message(ai_message) - chat_memory_instance.add(app_id, chat_message) + chat_memory_instance.add(app_id, session_id, chat_message) - assert chat_memory_instance.count_history_messages(app_id) == 1 - chat_memory_instance.delete_chat_history(app_id) + assert chat_memory_instance.count(app_id, session_id) == 1 + chat_memory_instance.delete(app_id, session_id) -def test_get_recent_memories(chat_memory_instance): +def test_get(chat_memory_instance): app_id = "test_app" + session_id = "test_session" for i in range(1, 7): human_message = f"Question {i}" @@ -36,15 +38,16 @@ def test_get_recent_memories(chat_memory_instance): chat_message.add_user_message(human_message) chat_message.add_ai_message(ai_message) - chat_memory_instance.add(app_id, chat_message) + chat_memory_instance.add(app_id, session_id, chat_message) - recent_memories = chat_memory_instance.get_recent_memories(app_id, num_rounds=5) + recent_memories = chat_memory_instance.get(app_id, session_id, num_rounds=5) assert len(recent_memories) == 5 def test_delete_chat_history(chat_memory_instance): app_id = "test_app" + session_id = "test_session" for i in range(1, 6): human_message = f"Question {i}" @@ -54,11 +57,11 @@ def test_delete_chat_history(chat_memory_instance): chat_message.add_user_message(human_message) chat_message.add_ai_message(ai_message) - chat_memory_instance.add(app_id, chat_message) + chat_memory_instance.add(app_id, session_id, chat_message) - chat_memory_instance.delete_chat_history(app_id) + chat_memory_instance.delete(app_id, session_id) - assert chat_memory_instance.count_history_messages(app_id) == 0 + assert chat_memory_instance.count(app_id, session_id) == 0 @pytest.fixture diff --git a/tests/memory/test_memory_messages.py b/tests/memory/test_memory_messages.py index 75d915a3..23f7b53b 100644 --- a/tests/memory/test_memory_messages.py +++ b/tests/memory/test_memory_messages.py @@ -3,17 +3,17 @@ from embedchain.memory.message import BaseMessage, ChatMessage def test_ec_base_message(): content = "Hello, how are you?" - creator = "human" + created_by = "human" metadata = {"key": "value"} - message = BaseMessage(content=content, creator=creator, metadata=metadata) + message = BaseMessage(content=content, created_by=created_by, metadata=metadata) assert message.content == content - assert message.creator == creator + assert message.created_by == created_by assert message.metadata == metadata assert message.type is None assert message.is_lc_serializable() is True - assert str(message) == f"{creator}: {content}" + assert str(message) == f"{created_by}: {content}" def test_ec_base_chat_message(): @@ -27,11 +27,11 @@ def test_ec_base_chat_message(): chat_message.add_ai_message(ai_message_content, metadata=ai_metadata) assert chat_message.human_message.content == human_message_content - assert chat_message.human_message.creator == "human" + assert chat_message.human_message.created_by == "human" assert chat_message.human_message.metadata == human_metadata assert chat_message.ai_message.content == ai_message_content - assert chat_message.ai_message.creator == "ai" + assert chat_message.ai_message.created_by == "ai" assert chat_message.ai_message.metadata == ai_metadata assert str(chat_message) == f"human: {human_message_content}\nai: {ai_message_content}"