SystemMessage class in LangChain

Posted: Nov 10, 2024.

The SystemMessage class in LangChain helps establish context and instructions for AI models. SystemMessage improves the quality and reliability of AI responses for more satisfying user experiences.

What is SystemMessage ?

LangChain includes several specialized message classes that extend from the BaseMessage class:

  • SystemMessage (provides context)
  • HumanMessage (captures user input)
  • ChatMessage (general interactions)
  • ToolMessage (tool outputs)
  • AIMessage (AI-generated responses)

Each inherits from BaseMessage but adds specific properties or methods for its role.

The SystemMessage class instructs AI behavior by setting initial context. It provides guidelines to shape AI responses.

By defining the parameters of how the AI should interact, SystemMessage makes sure that responses are not only accurate but also consistent with the desired persona or tone of the assistant.

Let's say that if you want your AI to adopt a friendly and casual tone or if you need it to be a formal subject matter expert, the SystemMessage is where you provide these instructions.

from langchain_core.messages.system import SystemMessage, HumanMessage

messages = [
    SystemMessage(
        content="You are a very helpful assistant! Your name is Bob."
    ),
    HumanMessage(
        content="What is your name?"
    )
]

# Alternatively, you can create a simpler SystemMessage as follows

from langchain.schema import SystemMessage

system_message = SystemMessage(content="You are a helpful AI assistant.")

This simple message sets the tone for the AI's behavior. Such initial context makes sure the AI meets user expectations effectively.

ParameterTypeDescription
contentUnion[str, List[Union[str, Dict]]]Required content of the message that defines the initial context.
additional_kwargsdict [Optional]Reserved for additional payload data associated with the message. Can include extra information like tool calls.
idOptional[str]Optional unique identifier for the message. Ideally provided by the provider/model.
nameOptional[str]Optional name for the message for easy identification.
response_metadatadict [Optional]Metadata about the response such as response headers or token counts.
typeLiteral['system'] = 'system'The type of the message, used for serialization purposes. Defaults to system.

Integrating SystemMessage with ChatOpenAI

To get started with LangChain you need to install the core packages:

pip install langchain langchain_community

Next, set your OpenAI API key as an environment variable using Python code:

import os
os.environ["OPENAI_API_KEY"] = "YOUR_API_KEY"

This key is necessary for accessing OpenAI's models in LangChain.

To use SystemMessage with ChatOpenAI include it in the list of messages that are passed to the model.

from langchain.chat_models import ChatOpenAI
from langchain.schema import SystemMessage, HumanMessage

system_message = SystemMessage(content="You are an expert on machine learning.")
human_message = HumanMessage(content="What is the difference between supervised and unsupervised learning?")

chat_model = ChatOpenAI(temperature=0.7)
response = chat_model([system_message, human_message])
print(response.content)

We have created a SystemMessage that tells the AI that it is an expert in machine learning. The subsequent HumanMessage asks a specific question and the AI uses the information from the SystemMessage to generate an appropriate response.

Using SystemMessage with ConversationalRetrievalChain

The SystemMessage can also be effectively integrated into more complex chains such as the ConversationalRetrievalChain. This is useful when combining conversational abilities with retrieval from an external knowledge base.

pip install tiktoken chromadb

This command installs additional libraries (tiktoken and chromadb) that help with tokenization and vector storage.

Now create a file source.txt and put your content to that file.

from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.text_splitter import CharacterTextSplitter
from langchain.llms import OpenAI
from langchain.chat_models import ChatOpenAI
from langchain.chains import ConversationalRetrievalChain
from langchain.document_loaders import TextLoader
from langchain.memory import ConversationBufferMemory
from langchain.prompts import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
    SystemMessagePromptTemplate,
)

system_message_prompt = SystemMessagePromptTemplate.from_template(
    "Your name is Roboto, you are a nice virtual assistant."
)
human_message_prompt = HumanMessagePromptTemplate.from_template(
    "{question}"
)

loader = TextLoader("./source.txt")
documents = loader.load()
text_splitter = CharacterTextSplitter(chunk_size=300, chunk_overlap=0)
documents = text_splitter.split_documents(documents)

embeddings = OpenAIEmbeddings()
vectorstore = Chroma.from_documents(documents, embeddings)

memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

chat_history = [
    ("my name is David, what's your name?", "Hello David! My name is Roboto. How can I assist you today?"),
]

# qa = ConversationalRetrievalChain.from_llm(OpenAI(temperature=0), vectorstore.as_retriever(), memory=memory)
chain = ConversationalRetrievalChain.from_llm(
    llm=ChatOpenAI(temperature=0),
    retriever=vectorstore.as_retriever(),
    memory=ConversationBufferMemory(
        memory_key="chat_history",
        return_messages=True,
    ),
    combine_docs_chain_kwargs={
        "prompt": ChatPromptTemplate.from_messages([
            system_message_prompt,
            human_message_prompt,
        ]),
    },
)


query = "do you know my name?"
result = chain({"question": query, "chat_history": chat_history})
print(result["answer"])

Users will receive targeted and relevant responses particularly when engaging with a specific knowledge focus.

Best Practices for SystemMessage

For optimal performance when using the SystemMessage class in your LangChain applications, consider the following best practices and insights

  1. Keep It Concise: Avoid lengthy messages to save tokens. Provide only essential context.

  2. Use Prompt Templates: Utilize PromptTemplate classes to parameterize messages for flexibility and reusability. This helps standardize instructions across different contexts and conversations

  3. Monitor Token Usage: Use token counting libraries to pre-calculate the size of both the system message and user inputs. This prevents running out of available tokens mid-conversation.

  4. Adapt SystemMessage for Different Contexts: Implement context-based logic to dynamically adjust the SystemMessage during runtime based on user input or interaction history.

  5. Address Conflicting Instructions: Analyze the content of SystemMessage to remove overlapping or unclear directives.

  6. Ensure Proper Recognition of SystemMessage: Validate the order and format of the message list. Make sure that SystemMessage is positioned correctly as the first input. Adjust model temperature settings for predictable behavior.

  7. Effective Integration with Retrieval: Use proper vector store settings and split documents carefully. Set up memory components like ConversationBufferMemory to ensure continuity in the AI's retrieval and responses.

To maintain effective responses with your SystemMessage you can use observability tools like Lunary to gain insights, detect issues and monitor token usage.

Integration with Lunary will help with quality AI interactions and optimize your SystemMessage implementations.

Building an AI chatbot?

Open-source GenAI monitoring, prompt management, and magic.

Learn More

Join 10,000+ subscribers

Every 2 weeks, latest model releases and industry news.

Building an AI chatbot?

Open-source GenAI monitoring, prompt management, and magic.

Learn More