mirror of
https://github.com/hwchase17/langchain.git
synced 2025-06-13 18:36:19 +00:00
242 lines
9.1 KiB
Plaintext
242 lines
9.1 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ac47bfab-0f4f-42ce-8bb6-898ef22a0338",
|
|
"metadata": {},
|
|
"source": [
|
|
"# How to merge consecutive messages of the same type\n",
|
|
"\n",
|
|
"Certain models do not support passing in consecutive [messages](/docs/concepts/messages/) of the same type (a.k.a. \"runs\" of the same message type).\n",
|
|
"\n",
|
|
"The `merge_message_runs` utility makes it easy to merge consecutive messages of the same type.\n",
|
|
"\n",
|
|
"### Setup"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "198ce37f-4466-45a2-8878-d75cd01a5d23",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%pip install -qU langchain-core langchain-anthropic"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b5c3ca6e-e5b3-4151-8307-9101713a20ae",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Basic usage"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"id": "1a215bbb-c05c-40b0-a6fd-d94884d517df",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"SystemMessage(content=\"you're a good assistant.\\nyou always respond with a joke.\", additional_kwargs={}, response_metadata={})\n",
|
|
"\n",
|
|
"HumanMessage(content=[{'type': 'text', 'text': \"i wonder why it's called langchain\"}, 'and who is harrison chasing anyways'], additional_kwargs={}, response_metadata={})\n",
|
|
"\n",
|
|
"AIMessage(content='Well, I guess they thought \"WordRope\" and \"SentenceString\" just didn\\'t have the same ring to it!\\nWhy, he\\'s probably chasing after the last cup of coffee in the office!', additional_kwargs={}, response_metadata={})\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"from langchain_core.messages import (\n",
|
|
" AIMessage,\n",
|
|
" HumanMessage,\n",
|
|
" SystemMessage,\n",
|
|
" merge_message_runs,\n",
|
|
")\n",
|
|
"\n",
|
|
"messages = [\n",
|
|
" SystemMessage(\"you're a good assistant.\"),\n",
|
|
" SystemMessage(\"you always respond with a joke.\"),\n",
|
|
" HumanMessage([{\"type\": \"text\", \"text\": \"i wonder why it's called langchain\"}]),\n",
|
|
" HumanMessage(\"and who is harrison chasing anyways\"),\n",
|
|
" AIMessage(\n",
|
|
" 'Well, I guess they thought \"WordRope\" and \"SentenceString\" just didn\\'t have the same ring to it!'\n",
|
|
" ),\n",
|
|
" AIMessage(\"Why, he's probably chasing after the last cup of coffee in the office!\"),\n",
|
|
"]\n",
|
|
"\n",
|
|
"merged = merge_message_runs(messages)\n",
|
|
"print(\"\\n\\n\".join([repr(x) for x in merged]))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0544c811-7112-4b76-8877-cc897407c738",
|
|
"metadata": {},
|
|
"source": [
|
|
"Notice that if the contents of one of the messages to merge is a list of content blocks then the merged message will have a list of content blocks. And if both messages to merge have string contents then those are concatenated with a newline character."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1b2eee74-71c8-4168-b968-bca580c25d18",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Chaining\n",
|
|
"\n",
|
|
"`merge_message_runs` can be used in an imperatively (like above) or declaratively, making it easy to compose with other components in a chain:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"id": "6d5a0283-11f8-435b-b27b-7b18f7693592",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Note: you may need to restart the kernel to use updated packages.\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"AIMessage(content=[], additional_kwargs={}, response_metadata={'id': 'msg_01KNGUMTuzBVfwNouLDpUMwf', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 84, 'output_tokens': 3}}, id='run-b908b198-9c24-450b-9749-9d4a8182937b-0', usage_metadata={'input_tokens': 84, 'output_tokens': 3, 'total_tokens': 87})"
|
|
]
|
|
},
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"from langchain_anthropic import ChatAnthropic\n",
|
|
"\n",
|
|
"llm = ChatAnthropic(model=\"claude-3-sonnet-20240229\", temperature=0)\n",
|
|
"# Notice we don't pass in messages. This creates\n",
|
|
"# a RunnableLambda that takes messages as input\n",
|
|
"merger = merge_message_runs()\n",
|
|
"chain = merger | llm\n",
|
|
"chain.invoke(messages)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "72e90dce-693c-4842-9526-ce6460fe956b",
|
|
"metadata": {},
|
|
"source": [
|
|
"Looking at the LangSmith trace we can see that before the messages are passed to the model they are merged: https://smith.langchain.com/public/ab558677-cac9-4c59-9066-1ecce5bcd87c/r\n",
|
|
"\n",
|
|
"Looking at just the merger, we can see that it's a Runnable object that can be invoked like all Runnables:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"id": "460817a6-c327-429d-958e-181a8c46059c",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"[SystemMessage(content=\"you're a good assistant.\\nyou always respond with a joke.\", additional_kwargs={}, response_metadata={}),\n",
|
|
" HumanMessage(content=[{'type': 'text', 'text': \"i wonder why it's called langchain\"}, 'and who is harrison chasing anyways'], additional_kwargs={}, response_metadata={}),\n",
|
|
" AIMessage(content='Well, I guess they thought \"WordRope\" and \"SentenceString\" just didn\\'t have the same ring to it!\\nWhy, he\\'s probably chasing after the last cup of coffee in the office!', additional_kwargs={}, response_metadata={})]"
|
|
]
|
|
},
|
|
"execution_count": 10,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"merger.invoke(messages)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4178837d-b155-492d-9404-d567accc1fa0",
|
|
"metadata": {},
|
|
"source": [
|
|
"`merge_message_runs` can also be placed after a prompt:"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"id": "620530ab-ed05-4899-b984-bfa4cd738465",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"AIMessage(content='A convergent series is an infinite series whose partial sums approach a finite value as more terms are added. In other words, the sequence of partial sums has a limit.\\n\\nMore formally, an infinite series Σ an (where an are the terms of the series) is said to be convergent if the sequence of partial sums:\\n\\nS1 = a1\\nS2 = a1 + a2 \\nS3 = a1 + a2 + a3\\n...\\nSn = a1 + a2 + a3 + ... + an\\n...\\n\\nconverges to some finite number S as n goes to infinity. We write:\\n\\nlim n→∞ Sn = S\\n\\nThe finite number S is called the sum of the convergent infinite series.\\n\\nIf the sequence of partial sums does not approach any finite limit, the infinite series is said to be divergent.\\n\\nSome key properties:\\n- A series converges if and only if the sequence of its partial sums is a Cauchy sequence.\\n- Absolute/conditional convergence criteria help determine if a given series converges.\\n- Convergent series have many important applications in mathematics, physics, engineering etc.', additional_kwargs={}, response_metadata={'id': 'msg_01MfV6y2hep7ZNvDz24A36U4', 'model': 'claude-3-sonnet-20240229', 'stop_reason': 'end_turn', 'stop_sequence': None, 'usage': {'input_tokens': 29, 'output_tokens': 267}}, id='run-9d925f58-021e-4bd0-94fc-f8f5e91010a4-0', usage_metadata={'input_tokens': 29, 'output_tokens': 267, 'total_tokens': 296})"
|
|
]
|
|
},
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"from langchain_core.prompts import ChatPromptTemplate\n",
|
|
"\n",
|
|
"prompt = ChatPromptTemplate(\n",
|
|
" [\n",
|
|
" (\"system\", \"You're great a {skill}\"),\n",
|
|
" (\"system\", \"You're also great at explaining things\"),\n",
|
|
" (\"human\", \"{query}\"),\n",
|
|
" ]\n",
|
|
")\n",
|
|
"chain = prompt | merger | llm\n",
|
|
"chain.invoke({\"skill\": \"math\", \"query\": \"what's the definition of a convergent series\"})"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "51ba533a-43c7-4e5f-bd91-a4ec23ceeb34",
|
|
"metadata": {},
|
|
"source": [
|
|
"LangSmith Trace: https://smith.langchain.com/public/432150b6-9909-40a7-8ae7-944b7e657438/r/f4ad5fb2-4d38-42a6-b780-25f62617d53f"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "4548d916-ce21-4dc6-8f19-eedb8003ace6",
|
|
"metadata": {},
|
|
"source": [
|
|
"## API reference\n",
|
|
"\n",
|
|
"For a complete description of all arguments head to the API reference: https://python.langchain.com/api_reference/core/messages/langchain_core.messages.utils.merge_message_runs.html"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "poetry-venv-2",
|
|
"language": "python",
|
|
"name": "poetry-venv-2"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.11.9"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|