Browse Source

[Bug Fix] Handle chat sessions properly during `app.chat()` calls (#1084)

Deshraj Yadav 1 year ago
parent
commit
a54dde0509

+ 12 - 13
embedchain/embedchain.py

@@ -7,9 +7,7 @@ from typing import Any, Dict, List, Optional, Tuple, Union
 from dotenv import load_dotenv
 from dotenv import load_dotenv
 from langchain.docstore.document import Document
 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.chunkers.base_chunker import BaseChunker
 from embedchain.config import AddConfig, BaseLlmConfig, ChunkerConfig
 from embedchain.config import AddConfig, BaseLlmConfig, ChunkerConfig
 from embedchain.config.base_app_config import BaseAppConfig
 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.helpers.json_serializable import JSONSerializable
 from embedchain.llm.base import BaseLlm
 from embedchain.llm.base import BaseLlm
 from embedchain.loaders.base_loader import BaseLoader
 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.telemetry.posthog import AnonymousTelemetry
 from embedchain.utils import detect_datatype, is_valid_json_string
 from embedchain.utils import detect_datatype, is_valid_json_string
 from embedchain.vectordb.base import BaseVectorDB
 from embedchain.vectordb.base import BaseVectorDB
@@ -580,6 +577,7 @@ class EmbedChain(JSONSerializable):
         input_query: str,
         input_query: str,
         config: Optional[BaseLlmConfig] = None,
         config: Optional[BaseLlmConfig] = None,
         dry_run=False,
         dry_run=False,
+        session_id: str = "default",
         where: Optional[Dict[str, str]] = None,
         where: Optional[Dict[str, str]] = None,
         citations: bool = False,
         citations: bool = False,
         **kwargs: Dict[str, Any],
         **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
         :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
         the LLM. The purpose is to test the prompt, not the response., defaults to False
         :type dry_run: bool, optional
         :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
         :param where: A dictionary of key-value pairs to filter the database results., defaults to None
         :type where: Optional[Dict[str, str]], optional
         :type where: Optional[Dict[str, str]], optional
         :param kwargs: To read more params for the query function. Ex. we use citations boolean
         :param kwargs: To read more params for the query function. Ex. we use citations boolean
@@ -616,6 +616,9 @@ class EmbedChain(JSONSerializable):
         else:
         else:
             contexts_data_for_llm_query = contexts
             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:
         if self.cache_config is not None:
             logging.info("Cache enabled. Checking cache...")
             logging.info("Cache enabled. Checking cache...")
             answer = adapt(
             answer = adapt(
@@ -634,7 +637,7 @@ class EmbedChain(JSONSerializable):
             )
             )
 
 
         # add conversation in memory
         # 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
         # Send anonymous telemetry
         self.telemetry.capture(event_name="chat", properties=self._telemetry_props)
         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)
         self.telemetry.capture(event_name="reset", properties=self._telemetry_props)
 
 
     def get_history(self, num_rounds: int = 10, display_format: bool = True):
     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)
         self.llm.update_history(app_id=self.config.id)

+ 19 - 8
embedchain/llm/base.py

@@ -8,7 +8,7 @@ from embedchain.config.llm.base import (DEFAULT_PROMPT,
                                         DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE,
                                         DEFAULT_PROMPT_WITH_HISTORY_TEMPLATE,
                                         DOCS_SITE_PROMPT_TEMPLATE)
                                         DOCS_SITE_PROMPT_TEMPLATE)
 from embedchain.helpers.json_serializable import JSONSerializable
 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
 from embedchain.memory.message import ChatMessage
 
 
 
 
@@ -24,7 +24,7 @@ class BaseLlm(JSONSerializable):
         else:
         else:
             self.config = config
             self.config = config
 
 
-        self.memory = ECChatMemory()
+        self.memory = ChatHistory()
         self.is_docs_site_instance = False
         self.is_docs_site_instance = False
         self.online = False
         self.online = False
         self.history: Any = None
         self.history: Any = None
@@ -45,17 +45,24 @@ class BaseLlm(JSONSerializable):
         """
         """
         self.history = history
         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)"""
         """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])
         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 = ChatMessage()
         chat_message.add_user_message(question, metadata=metadata)
         chat_message.add_user_message(question, metadata=metadata)
         chat_message.add_ai_message(answer, 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:
     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
                 # Restore previous config
                 self.config: BaseLlmConfig = BaseLlmConfig.deserialize(prev_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.
         Queries the vector database on the given input query.
         Gets relevant doc based on the query and then passes it to an
         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
         :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
         the LLM. The purpose is to test the prompt, not the response., defaults to False
         :type dry_run: bool, optional
         :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
         :return: The answer to the query or the dry run result
         :rtype: str
         :rtype: str
         """
         """

+ 48 - 41
embedchain/memory/base.py

@@ -9,40 +9,41 @@ from embedchain.memory.message import ChatMessage
 from embedchain.memory.utils import merge_metadata_dict
 from embedchain.memory.utils import merge_metadata_dict
 
 
 CHAT_MESSAGE_CREATE_TABLE_QUERY = """
 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)
-            )
-            """
-
-
-class ECChatMemory:
+    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 ChatHistory:
     def __init__(self) -> None:
     def __init__(self) -> None:
         with sqlite3.connect(SQLITE_PATH, check_same_thread=False) as self.connection:
         with sqlite3.connect(SQLITE_PATH, check_same_thread=False) as self.connection:
             self.cursor = self.connection.cursor()
             self.cursor = self.connection.cursor()
-
             self.cursor.execute(CHAT_MESSAGE_CREATE_TABLE_QUERY)
             self.cursor.execute(CHAT_MESSAGE_CREATE_TABLE_QUERY)
             self.connection.commit()
             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())
         memory_id = str(uuid.uuid4())
         metadata_dict = merge_metadata_dict(chat_message.human_message.metadata, chat_message.ai_message.metadata)
         metadata_dict = merge_metadata_dict(chat_message.human_message.metadata, chat_message.ai_message.metadata)
         if metadata_dict:
         if metadata_dict:
             metadata = self._serialize_json(metadata_dict)
             metadata = self._serialize_json(metadata_dict)
         ADD_CHAT_MESSAGE_QUERY = """
         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(
         self.cursor.execute(
             ADD_CHAT_MESSAGE_QUERY,
             ADD_CHAT_MESSAGE_QUERY,
             (
             (
                 app_id,
                 app_id,
                 memory_id,
                 memory_id,
+                session_id,
                 chat_message.human_message.content,
                 chat_message.human_message.content,
                 chat_message.ai_message.content,
                 chat_message.ai_message.content,
                 metadata if metadata_dict else "{}",
                 metadata if metadata_dict else "{}",
@@ -52,37 +53,41 @@ class ECChatMemory:
         logging.info(f"Added chat memory to db with id: {memory_id}")
         logging.info(f"Added chat memory to db with id: {memory_id}")
         return 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()
         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
         Get the most recent num_rounds rounds of conversations
         between human and AI, for a given app_id.
         between human and AI, for a given app_id.
         """
         """
 
 
         QUERY = """
         QUERY = """
-            SELECT * FROM chat_history
-            WHERE app_id=?
+            SELECT * FROM ec_chat_history
+            WHERE app_id=? AND session_id=?
             ORDER BY created_at DESC
             ORDER BY created_at DESC
             LIMIT ?
             LIMIT ?
         """
         """
         self.cursor.execute(
         self.cursor.execute(
             QUERY,
             QUERY,
-            (app_id, num_rounds),
+            (app_id, session_id, num_rounds),
         )
         )
 
 
         results = self.cursor.fetchall()
         results = self.cursor.fetchall()
         history = []
         history = []
         for result in results:
         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)
             metadata = self._deserialize_json(metadata=metadata)
             # Return list of dict if display_format is True
             # Return list of dict if display_format is True
             if display_format:
             if display_format:
@@ -94,6 +99,20 @@ class ECChatMemory:
                 history.append(memory)
                 history.append(memory)
         return history
         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]):
     def _serialize_json(self, metadata: Dict[str, Any]):
         return json.dumps(metadata)
         return json.dumps(metadata)
 
 
@@ -102,15 +121,3 @@ class ECChatMemory:
 
 
     def close_connection(self):
     def close_connection(self):
         self.connection.close()
         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

+ 7 - 7
embedchain/memory/message.py

@@ -14,16 +14,16 @@ class BaseMessage(JSONSerializable):
     # The string content of the message.
     # The string content of the message.
     content: str
     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.
     # Any additional info.
     metadata: Dict[str, Any]
     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__()
         super().__init__()
         self.content = content
         self.content = content
-        self.creator = creator
+        self.created_by = created_by
         self.metadata = metadata
         self.metadata = metadata
 
 
     @property
     @property
@@ -36,7 +36,7 @@ class BaseMessage(JSONSerializable):
         return True
         return True
 
 
     def __str__(self) -> str:
     def __str__(self) -> str:
-        return f"{self.creator}: {self.content}"
+        return f"{self.created_by}: {self.content}"
 
 
 
 
 class ChatMessage(JSONSerializable):
 class ChatMessage(JSONSerializable):
@@ -57,7 +57,7 @@ class ChatMessage(JSONSerializable):
                 overwritting it with new message."
                 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):
     def add_ai_message(self, message: str, metadata: Optional[dict] = None):
         if self.ai_message:
         if self.ai_message:
@@ -66,7 +66,7 @@ class ChatMessage(JSONSerializable):
                 overwritting it with new message."
                 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:
     def __str__(self) -> str:
         return f"{self.human_message}\n{self.ai_message}"
         return f"{self.human_message}\n{self.ai_message}"

+ 10 - 93
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]]
 [[package]]
 name = "aiofiles"
 name = "aiofiles"
@@ -354,26 +354,6 @@ description = "The uncompromising code formatter."
 optional = false
 optional = false
 python-versions = ">=3.8"
 python-versions = ">=3.8"
 files = [
 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-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"},
     {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"},
     {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_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-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-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-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_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73b2f1922a39d5d59cc0e597987300df3396b148a9bd10b76a058a2f2772fc04"},
     {file = "greenlet-3.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1e22c22f7826096ad503e9bb681b05b8c1f5a8138469b255eb91f26a76634f2"},
     {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_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-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-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_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_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ecf94aa539e97a8411b5ea52fc6ccd8371be9550c4041011a091eb8b3ca1d810"},
     {file = "greenlet-3.0.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80dcd3c938cbcac986c5c92779db8e8ce51a89a849c135172c88ecbdc8c056b7"},
     {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-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-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"},
     {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"},
     {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-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_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"},
     {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]
 [package.dependencies]
 numpy = [
 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\""},
     {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_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_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-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-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
     {file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
     {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"},
     {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_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_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-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-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
     {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
     {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-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_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
     {file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
     {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_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_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-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-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
     {file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
     {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"},
     {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_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_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-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-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
     {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
     {file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
     {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
     {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_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-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-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_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-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"},
     {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
 optional = false
 python-versions = ">=3.7"
 python-versions = ">=3.7"
 files = [
 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_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-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_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-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-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_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-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"},
     {file = "SQLAlchemy-2.0.22.tar.gz", hash = "sha256:5434cc601aa17570d79e5377f5fd45ff92f9379e2abed0be5e8c2fba8d353d2b"},
 ]
 ]
 
 
@@ -8205,4 +8122,4 @@ youtube = ["youtube-transcript-api", "yt_dlp"]
 [metadata]
 [metadata]
 lock-version = "2.0"
 lock-version = "2.0"
 python-versions = ">=3.9,<3.12"
 python-versions = ">=3.9,<3.12"
-content-hash = "335c42c91a2b5e4a1c3d8a7c39dee8665fd1eee0410e1bc6cb6cb1d6f6722445"
+content-hash = "2d59f37483caac14b4c0e10331facdab174deba143480df53340756330214010"

+ 1 - 1
pyproject.toml

@@ -1,6 +1,6 @@
 [tool.poetry]
 [tool.poetry]
 name = "embedchain"
 name = "embedchain"
-version = "0.1.48"
+version = "0.1.49"
 description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data"
 description = "Data platform for LLMs - Load, index, retrieve and sync any unstructured data"
 authors = [
 authors = [
     "Taranjeet Singh <taranjeet@embedchain.ai>",
     "Taranjeet Singh <taranjeet@embedchain.ai>",

+ 3 - 3
tests/embedchain/test_embedchain.py

@@ -7,7 +7,7 @@ from embedchain import App
 from embedchain.config import AppConfig, ChromaDbConfig
 from embedchain.config import AppConfig, ChromaDbConfig
 from embedchain.embedchain import EmbedChain
 from embedchain.embedchain import EmbedChain
 from embedchain.llm.base import BaseLlm
 from embedchain.llm.base import BaseLlm
-from embedchain.memory.base import ECChatMemory
+from embedchain.memory.base import ChatHistory
 from embedchain.vectordb.chroma import ChromaDB
 from embedchain.vectordb.chroma import ChromaDB
 
 
 os.environ["OPENAI_API_KEY"] = "test-api-key"
 os.environ["OPENAI_API_KEY"] = "test-api-key"
@@ -31,7 +31,7 @@ def test_whole_app(app_instance, mocker):
         BaseLlm,
         BaseLlm,
         "add_history",
         "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.add(knowledge, data_type="text")
     app_instance.query("What text did I give you?")
     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)
     app_instance = App(config=config, db=db)
 
 
     # mock delete chat history
     # mock delete chat history
-    mocker.patch.object(ECChatMemory, "delete_chat_history", autospec=True)
+    mocker.patch.object(ChatHistory, "delete", autospec=True)
 
 
     app_instance.reset()
     app_instance.reset()
 
 

+ 5 - 5
tests/llm/test_chat.py

@@ -5,7 +5,7 @@ from unittest.mock import MagicMock, patch
 from embedchain import App
 from embedchain import App
 from embedchain.config import AppConfig, BaseLlmConfig
 from embedchain.config import AppConfig, BaseLlmConfig
 from embedchain.llm.base import BaseLlm
 from embedchain.llm.base import BaseLlm
-from embedchain.memory.base import ECChatMemory
+from embedchain.memory.base import ChatHistory
 from embedchain.memory.message import ChatMessage
 from embedchain.memory.message import ChatMessage
 
 
 
 
@@ -36,11 +36,11 @@ class TestApp(unittest.TestCase):
         with patch.object(BaseLlm, "add_history") as mock_history:
         with patch.object(BaseLlm, "add_history") as mock_history:
             first_answer = app.chat("Test query 1")
             first_answer = app.chat("Test query 1")
             self.assertEqual(first_answer, "Test answer")
             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")
             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(App, "_retrieve_from_database", return_value=["Test context"])
     @patch.object(BaseLlm, "get_answer_from_llm", return_value="Test answer")
     @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
         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 = ChatMessage()
             mock_message.add_user_message("Test query 1")
             mock_message.add_user_message("Test query 1")
             mock_message.add_ai_message("Test answer")
             mock_message.add_ai_message("Test answer")

+ 15 - 12
tests/memory/test_chat_memory.py

@@ -1,17 +1,18 @@
 import pytest
 import pytest
 
 
-from embedchain.memory.base import ECChatMemory
+from embedchain.memory.base import ChatHistory
 from embedchain.memory.message import ChatMessage
 from embedchain.memory.message import ChatMessage
 
 
 
 
-# Fixture for creating an instance of ECChatMemory
+# Fixture for creating an instance of ChatHistory
 @pytest.fixture
 @pytest.fixture
 def chat_memory_instance():
 def chat_memory_instance():
-    return ECChatMemory()
+    return ChatHistory()
 
 
 
 
 def test_add_chat_memory(chat_memory_instance):
 def test_add_chat_memory(chat_memory_instance):
     app_id = "test_app"
     app_id = "test_app"
+    session_id = "test_session"
     human_message = "Hello, how are you?"
     human_message = "Hello, how are you?"
     ai_message = "I'm fine, thank 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_user_message(human_message)
     chat_message.add_ai_message(ai_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"
     app_id = "test_app"
+    session_id = "test_session"
 
 
     for i in range(1, 7):
     for i in range(1, 7):
         human_message = f"Question {i}"
         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_user_message(human_message)
         chat_message.add_ai_message(ai_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
     assert len(recent_memories) == 5
 
 
 
 
 def test_delete_chat_history(chat_memory_instance):
 def test_delete_chat_history(chat_memory_instance):
     app_id = "test_app"
     app_id = "test_app"
+    session_id = "test_session"
 
 
     for i in range(1, 6):
     for i in range(1, 6):
         human_message = f"Question {i}"
         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_user_message(human_message)
         chat_message.add_ai_message(ai_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
 @pytest.fixture

+ 6 - 6
tests/memory/test_memory_messages.py

@@ -3,17 +3,17 @@ from embedchain.memory.message import BaseMessage, ChatMessage
 
 
 def test_ec_base_message():
 def test_ec_base_message():
     content = "Hello, how are you?"
     content = "Hello, how are you?"
-    creator = "human"
+    created_by = "human"
     metadata = {"key": "value"}
     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.content == content
-    assert message.creator == creator
+    assert message.created_by == created_by
     assert message.metadata == metadata
     assert message.metadata == metadata
     assert message.type is None
     assert message.type is None
     assert message.is_lc_serializable() is True
     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():
 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)
     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.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.human_message.metadata == human_metadata
 
 
     assert chat_message.ai_message.content == ai_message_content
     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 chat_message.ai_message.metadata == ai_metadata
 
 
     assert str(chat_message) == f"human: {human_message_content}\nai: {ai_message_content}"
     assert str(chat_message) == f"human: {human_message_content}\nai: {ai_message_content}"