Files
mem0/cookbooks/customer-support-chatbot.ipynb
T

29 KiB

In [1]:
import os
from typing import List, Dict
from mem0 import Memory
from datetime import datetime
import anthropic

# Set up environment variables
os.environ["OPENAI_API_KEY"] = "your_openai_api_key" # needed for embedding model
os.environ["ANTHROPIC_API_KEY"] = "your_anthropic_api_key"
In [2]:
class SupportChatbot:
    def __init__(self):
        # Initialize Mem0 with Anthropic's Claude
        self.config = {
            "llm": {
                "provider": "anthropic",
                "config": {
                    "model": "claude-3-5-sonnet-latest",
                    "temperature": 0.1,
                    "max_tokens": 2000,
                }
            }
        }
        self.client = anthropic.Client(api_key=os.environ["ANTHROPIC_API_KEY"])
        self.memory = Memory.from_config(self.config)

        # Define support context
        self.system_context = """
        You are a helpful customer support agent. Use the following guidelines:
        - Be polite and professional
        - Show empathy for customer issues
        - Reference past interactions when relevant
        - Maintain consistent information across conversations
        - If you're unsure about something, ask for clarification
        - Keep track of open issues and follow-ups
        """

    def store_customer_interaction(self,
                                 user_id: str,
                                 message: str,
                                 response: str,
                                 metadata: Dict = None):
        """Store customer interaction in memory."""
        if metadata is None:
            metadata = {}

        # Add timestamp to metadata
        metadata["timestamp"] = datetime.now().isoformat()

        # Format conversation for storage
        conversation = [
            {"role": "user", "content": message},
            {"role": "assistant", "content": response}
        ]

        # Store in Mem0
        self.memory.add(
            conversation,
            user_id=user_id,
            metadata=metadata
        )

    def get_relevant_history(self, user_id: str, query: str) -> List[Dict]:
        """Retrieve relevant past interactions."""
        return self.memory.search(
            query=query,
            user_id=user_id,
            limit=5  # Adjust based on needs
        )

    def handle_customer_query(self, user_id: str, query: str) -> str:
        """Process customer query with context from past interactions."""

        # Get relevant past interactions
        relevant_history = self.get_relevant_history(user_id, query)

        # Build context from relevant history
        context = "Previous relevant interactions:\n"
        for memory in relevant_history:
            context += f"Customer: {memory['memory']}\n"
            context += f"Support: {memory['memory']}\n"
            context += "---\n"

        # Prepare prompt with context and current query
        prompt = f"""
        {self.system_context}

        {context}

        Current customer query: {query}

        Provide a helpful response that takes into account any relevant past interactions.
        """

        # Generate response using Claude
        response = self.client.messages.create(
            model="claude-3-5-sonnet-latest",
            messages=[{"role": "user", "content": prompt}],
            max_tokens=2000,
            temperature=0.1
        )

        # Store interaction
        self.store_customer_interaction(
            user_id=user_id,
            message=query,
            response=response,
            metadata={"type": "support_query"}
        )

        return response.content[0].text
In [3]:
chatbot = SupportChatbot()
user_id = "customer_bot"
print("Welcome to Customer Support! Type 'exit' to end the conversation.")

while True:
    # Get user input
    query = input()
    print("Customer:", query)
    
    # Check if user wants to exit
    if query.lower() == 'exit':
        print("Thank you for using our support service. Goodbye!")
        break
    
    # Handle the query and print the response
    response = chatbot.handle_customer_query(user_id, query)
    print("Support:", response, "\n\n")
Welcome to Customer Support! Type 'exit' to end the conversation.
Customer: Hi, I'm having trouble connecting my new smartwatch to the mobile app. It keeps showing a connection error.
/var/folders/5x/9kmqjfm947g5yh44m7fjk75r0000gn/T/ipykernel_91762/3000273332.py:55: DeprecationWarning: The current get_all API output format is deprecated. To use the latest format, set `api_version='v1.1'`. The current format will be removed in mem0ai 1.1.0 and later versions.
  return self.memory.search(
/var/folders/5x/9kmqjfm947g5yh44m7fjk75r0000gn/T/ipykernel_91762/3000273332.py:47: DeprecationWarning: The current add API output format is deprecated. To use the latest format, set `api_version='v1.1'`. The current format will be removed in mem0ai 1.1.0 and later versions.
  self.memory.add(
Support: Hello! Thank you for reaching out about the connection issue with your smartwatch. I understand how frustrating it can be when a new device won't connect properly. I'll be happy to help you resolve this.

To better assist you, could you please provide me with:
1. The model of your smartwatch
2. The type of phone you're using (iOS or Android)
3. Whether you've already installed the companion app and if it's the latest version

In the meantime, here are some general troubleshooting steps you can try:
1. Ensure Bluetooth is enabled on your phone
2. Restart both your smartwatch and phone
3. Make sure your smartwatch is sufficiently charged
4. Check if your phone's operating system is up to date

Once you provide those additional details, I can give you more specific guidance to resolve the connection error. Would you mind sharing that information? 


Customer: The connection issue is still happening even after trying the steps you suggested.
Support: I apologize that you're still experiencing connection issues with your smartwatch even after trying the previous troubleshooting steps. I understand how frustrating this must be for you. Let's try some additional steps to resolve this persistent problem.

Before we proceed, could you please confirm:
1. Which specific steps you've already attempted?
2. Are you seeing any particular error message on the screen?
3. What model of smartwatch and phone are you using?

This information will help me provide more targeted solutions and avoid suggesting steps you've already tried. In the meantime, here are a couple of additional troubleshooting steps we can try:

1. Completely reset the Bluetooth connection:
   - Turn off Bluetooth on your phone
   - Restart both your phone and smartwatch
   - Turn Bluetooth back on and attempt to pair again

2. Check if your smartwatch firmware is up to date

Would you be able to try these steps and let me know the results? I'll stay with you until we resolve this issue. 


Customer: 
---------------------------------------------------------------------------
BadRequestError                           Traceback (most recent call last)
Cell In[3], line 16
     13     break
     15 # Handle the query and print the response
---> 16 response = chatbot.handle_customer_query(user_id, query)
     17 print("Support:", response, "\n\n")

Cell In[2], line 65, in SupportChatbot.handle_customer_query(self, user_id, query)
     62 """Process customer query with context from past interactions."""
     64 # Get relevant past interactions
---> 65 relevant_history = self.get_relevant_history(user_id, query)
     67 # Build context from relevant history
     68 context = "Previous relevant interactions:\n"

Cell In[2], line 55, in SupportChatbot.get_relevant_history(self, user_id, query)
     53 def get_relevant_history(self, user_id: str, query: str) -> List[Dict]:
     54     """Retrieve relevant past interactions."""
---> 55     return self.memory.search(
     56         query=query,
     57         user_id=user_id,
     58         limit=5  # Adjust based on needs
     59     )

File ~/Desktop/mem0/.venv/lib/python3.12/site-packages/mem0/memory/main.py:404, in Memory.search(self, query, user_id, agent_id, run_id, limit, filters)
    396     future_graph_entities = (
    397         executor.submit(self.graph.search, query, filters, limit)
    398         if self.version == "v1.1" and self.enable_graph
    399         else None
    400     )
    402     concurrent.futures.wait([future_memories, future_graph_entities] if future_graph_entities else [future_memories])
--> 404     original_memories = future_memories.result()
    405     graph_entities = future_graph_entities.result() if future_graph_entities else None
    407 if self.version == "v1.1":

File /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/concurrent/futures/_base.py:449, in Future.result(self, timeout)
    447     raise CancelledError()
    448 elif self._state == FINISHED:
--> 449     return self.__get_result()
    451 self._condition.wait(timeout)
    453 if self._state in [CANCELLED, CANCELLED_AND_NOTIFIED]:

File /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/concurrent/futures/_base.py:401, in Future.__get_result(self)
    399 if self._exception:
    400     try:
--> 401         raise self._exception
    402     finally:
    403         # Break a reference cycle with the exception in self._exception
    404         self = None

File /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/concurrent/futures/thread.py:58, in _WorkItem.run(self)
     55     return
     57 try:
---> 58     result = self.fn(*self.args, **self.kwargs)
     59 except BaseException as exc:
     60     self.future.set_exception(exc)

File ~/Desktop/mem0/.venv/lib/python3.12/site-packages/mem0/memory/main.py:423, in Memory._search_vector_store(self, query, filters, limit)
    422 def _search_vector_store(self, query, filters, limit):
--> 423     embeddings = self.embedding_model.embed(query)
    424     memories = self.vector_store.search(query=embeddings, limit=limit, filters=filters)
    426     excluded_keys = {
    427         "user_id",
    428         "agent_id",
   (...)
    433         "updated_at",
    434     }

File ~/Desktop/mem0/.venv/lib/python3.12/site-packages/mem0/embeddings/openai.py:32, in OpenAIEmbedding.embed(self, text)
     22 """
     23 Get the embedding for the given text using OpenAI.
     24 
   (...)
     29     list: The embedding vector.
     30 """
     31 text = text.replace("\n", " ")
---> 32 return self.client.embeddings.create(input=[text], model=self.config.model).data[0].embedding

File ~/Desktop/mem0/.venv/lib/python3.12/site-packages/openai/resources/embeddings.py:124, in Embeddings.create(self, input, model, dimensions, encoding_format, user, extra_headers, extra_query, extra_body, timeout)
    118         embedding.embedding = np.frombuffer(  # type: ignore[no-untyped-call]
    119             base64.b64decode(data), dtype="float32"
    120         ).tolist()
    122     return obj
--> 124 return self._post(
    125     "/embeddings",
    126     body=maybe_transform(params, embedding_create_params.EmbeddingCreateParams),
    127     options=make_request_options(
    128         extra_headers=extra_headers,
    129         extra_query=extra_query,
    130         extra_body=extra_body,
    131         timeout=timeout,
    132         post_parser=parser,
    133     ),
    134     cast_to=CreateEmbeddingResponse,
    135 )

File ~/Desktop/mem0/.venv/lib/python3.12/site-packages/openai/_base_client.py:1270, in SyncAPIClient.post(self, path, cast_to, body, options, files, stream, stream_cls)
   1256 def post(
   1257     self,
   1258     path: str,
   (...)
   1265     stream_cls: type[_StreamT] | None = None,
   1266 ) -> ResponseT | _StreamT:
   1267     opts = FinalRequestOptions.construct(
   1268         method="post", url=path, json_data=body, files=to_httpx_files(files), **options
   1269     )
-> 1270     return cast(ResponseT, self.request(cast_to, opts, stream=stream, stream_cls=stream_cls))

File ~/Desktop/mem0/.venv/lib/python3.12/site-packages/openai/_base_client.py:947, in SyncAPIClient.request(self, cast_to, options, remaining_retries, stream, stream_cls)
    944 else:
    945     retries_taken = 0
--> 947 return self._request(
    948     cast_to=cast_to,
    949     options=options,
    950     stream=stream,
    951     stream_cls=stream_cls,
    952     retries_taken=retries_taken,
    953 )

File ~/Desktop/mem0/.venv/lib/python3.12/site-packages/openai/_base_client.py:1051, in SyncAPIClient._request(self, cast_to, options, retries_taken, stream, stream_cls)
   1048         err.response.read()
   1050     log.debug("Re-raising status error")
-> 1051     raise self._make_status_error_from_response(err.response) from None
   1053 return self._process_response(
   1054     cast_to=cast_to,
   1055     options=options,
   (...)
   1059     retries_taken=retries_taken,
   1060 )

BadRequestError: Error code: 400 - {'error': {'message': "'$.input' is invalid. Please check the API reference: https://platform.openai.com/docs/api-reference.", 'type': 'invalid_request_error', 'param': None, 'code': None}}