mirror of
https://github.com/hwchase17/langchain.git
synced 2026-02-21 14:43:07 +00:00
x
This commit is contained in:
@@ -104,10 +104,18 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 39,
|
||||
"execution_count": 3,
|
||||
"id": "8b6e1063-cf3a-456a-bf7d-830e5c1d2864",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/tmp/ipykernel_2459205/1840360377.py:24: LangChainDeprecationWarning: The class `LLMChain` was deprecated in LangChain 0.1.17 and will be removed in 1.0. Use RunnableSequence, e.g., `prompt | llm` instead.\n",
|
||||
" legacy_chain = LLMChain(\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
@@ -155,17 +163,17 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 40,
|
||||
"execution_count": 4,
|
||||
"id": "c7fa1618",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'Your name is Bob. How can I assist you today, Bob?'"
|
||||
"'Your name is Bob. How can I assist you further, Bob?'"
|
||||
]
|
||||
},
|
||||
"execution_count": 40,
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -192,7 +200,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 43,
|
||||
"execution_count": 5,
|
||||
"id": "e591965c-c4d7-4df7-966d-4d14bd46e157",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -205,13 +213,13 @@
|
||||
"hi! I'm bob\n",
|
||||
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
||||
"\n",
|
||||
"Hello Bob! How can I assist you today?\n",
|
||||
"Hello, Bob! How can I assist you today?\n",
|
||||
"================================\u001b[1m Human Message \u001b[0m=================================\n",
|
||||
"\n",
|
||||
"what was my name?\n",
|
||||
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
||||
"\n",
|
||||
"I'm sorry, I don't have the ability to know your name unless you tell me. Feel free to share it with me if you'd like.\n"
|
||||
"I'm sorry, but I do not have the ability to know your name as I am an AI assistant.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -298,17 +306,25 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 67,
|
||||
"execution_count": 6,
|
||||
"id": "dc2928de-d7a4-4f87-ab96-59bde9a3829f",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/home/eugene/.pyenv/versions/3.11.4/envs/core/lib/python3.11/site-packages/langsmith/client.py:5301: LangChainBetaWarning: The function `loads` is in beta. It is actively being worked on, so the API may change.\n",
|
||||
" prompt = loads(json.dumps(prompt_object.manifest))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{'input': 'hi! my name is bob what is my age?', 'chat_history': [HumanMessage(content='hi! my name is bob what is my age?', additional_kwargs={}, response_metadata={}), AIMessage(content='Hello Bob! You are 42 years old. If you need any more assistance or information, feel free to ask!', additional_kwargs={}, response_metadata={})], 'output': 'Hello Bob! You are 42 years old. If you need any more assistance or information, feel free to ask!'}\n",
|
||||
"{'input': 'hi! my name is bob what is my age?', 'chat_history': [HumanMessage(content='hi! my name is bob what is my age?', additional_kwargs={}, response_metadata={}), AIMessage(content='Hello Bob! You are 42 years old. If you need any more assistance or have any other questions, feel free to ask!', additional_kwargs={}, response_metadata={})], 'output': 'Hello Bob! You are 42 years old. If you need any more assistance or have any other questions, feel free to ask!'}\n",
|
||||
"\n",
|
||||
"{'input': 'do you remember my name?', 'chat_history': [HumanMessage(content='hi! my name is bob what is my age?', additional_kwargs={}, response_metadata={}), AIMessage(content='Hello Bob! You are 42 years old. If you need any more assistance or information, feel free to ask!', additional_kwargs={}, response_metadata={}), HumanMessage(content='do you remember my name?', additional_kwargs={}, response_metadata={}), AIMessage(content='Yes, your name is Bob. How can I assist you further, Bob?', additional_kwargs={}, response_metadata={})], 'output': 'Yes, your name is Bob. How can I assist you further, Bob?'}\n"
|
||||
"{'input': 'do you remember my name?', 'chat_history': [HumanMessage(content='hi! my name is bob what is my age?', additional_kwargs={}, response_metadata={}), AIMessage(content='Hello Bob! You are 42 years old. If you need any more assistance or have any other questions, feel free to ask!', additional_kwargs={}, response_metadata={}), HumanMessage(content='do you remember my name?', additional_kwargs={}, response_metadata={}), AIMessage(content='Yes, your name is Bob. How can I assist you further, Bob?', additional_kwargs={}, response_metadata={})], 'output': 'Yes, your name is Bob. How can I assist you further, Bob?'}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -333,7 +349,6 @@
|
||||
"\n",
|
||||
"tools = [get_user_age]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Get the prompt to use - you can modify this!\n",
|
||||
"prompt = hub.pull(\"hwchase17/openai-functions-agent\")\n",
|
||||
"\n",
|
||||
@@ -377,7 +392,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 68,
|
||||
"execution_count": 7,
|
||||
"id": "bdb29c9b-bc57-4512-9430-c5d5e3f91e3c",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -390,8 +405,8 @@
|
||||
"hi! I'm bob. What is my age?\n",
|
||||
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
||||
"Tool Calls:\n",
|
||||
" get_user_age (call_l3dpzCgvONmrcAuksHxKfcsa)\n",
|
||||
" Call ID: call_l3dpzCgvONmrcAuksHxKfcsa\n",
|
||||
" get_user_age (call_ewWp6keHVouwJyM4lRhk4X25)\n",
|
||||
" Call ID: call_ewWp6keHVouwJyM4lRhk4X25\n",
|
||||
" Args:\n",
|
||||
" name: bob\n",
|
||||
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
||||
@@ -464,7 +479,7 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 69,
|
||||
"execution_count": 8,
|
||||
"id": "fe63e424-1111-4f6a-a9c9-0887eb150ab0",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -477,7 +492,7 @@
|
||||
"hi! do you remember my name?\n",
|
||||
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
||||
"\n",
|
||||
"Hello! I'm sorry, but I don't have the capability to remember personal information like names. If you could remind me of your name, I'd be happy to assist you further!\n"
|
||||
"Hello! Yes, I remember your name. It's great to see you again! How can I assist you today?\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
@@ -500,9 +515,9 @@
|
||||
"source": [
|
||||
"</details>\n",
|
||||
"\n",
|
||||
"## Add Conversation History Processing\n",
|
||||
"## Implementing Conversation History Processing\n",
|
||||
"\n",
|
||||
"All the memory types below add some additional logic to process the conversation history.\n",
|
||||
"Each of the following memory types applies specific logic to handle the conversation history:\n",
|
||||
"\n",
|
||||
"| Memory Type | Description |\n",
|
||||
"|---------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|\n",
|
||||
@@ -511,19 +526,33 @@
|
||||
"| `ConversationSummaryMemory` | Continually summarizes the conversation history. The summary is updated after each conversation turn. The abstraction returns the summary of the conversation history. |\n",
|
||||
"| `ConversationSummaryBufferMemory` | Provides a running summary of the conversation together with the most recent messages in the conversation under the constraint that the total number of tokens in the conversation does not exceed a certain limit. |\n",
|
||||
"\n",
|
||||
"The general approach involves writing the necessary logic for processing conversation history and integrating it at the correct point.\n",
|
||||
"\n",
|
||||
"The general logic is to write the processing logic that you need for the conversation history and then add it in the appropriate place depending.\n",
|
||||
"We’ll start by building a simple processor using LangChain's built-in [trim_messages](https://python.langchain.com/api_reference/core/messages/langchain_core.messages.utils.trim_messages.html) function, and then demonstrate how to integrate it into your application.\n",
|
||||
"\n",
|
||||
"We'll create a simple processor using `LangChain's` [trim_messages](https://python.langchain.com/api_reference/core/messages/langchain_core.messages.utils.trim_messages.html) built in functionality, and then see how to plug it into your application.\n",
|
||||
"You can later replace this basic setup with more advanced logic tailored to your specific needs.\n",
|
||||
"\n",
|
||||
"\n",
|
||||
":::important\n",
|
||||
"\n",
|
||||
"We’ll begin by exploring a straightforward method that involves applying processing logic to the entire conversation history.\n",
|
||||
"\n",
|
||||
"While this approach is easy to test and implement, it has a downside: as the conversation grows, s\n",
|
||||
"o does the latency, since the logic is re-applied to all previous exchanges at each turn.\n",
|
||||
"\n",
|
||||
"More advanced strategies focus on incrementally updating the conversation history to avoid redundant processing.\n",
|
||||
"\n",
|
||||
"For instance, the langgraph [how-to guide on summarization](https://langchain-ai.github.io/langgraph/how-tos/memory/add-summary-conversation-history/) demonstrates\n",
|
||||
"how to maintain a running summary of the conversation while discarding older messages, ensuring they aren't re-processed during later turns.\n",
|
||||
":::\n",
|
||||
"\n",
|
||||
"You can later replace the logic with more complex logic that's better suited for your use case.\n",
|
||||
"\n",
|
||||
"### ConversationBufferWindowMemory, ConversationTokenBufferMemory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 70,
|
||||
"execution_count": 12,
|
||||
"id": "a501806e-deac-458c-88b1-b615efde9930",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -534,10 +563,10 @@
|
||||
" AIMessage(content=\"Hmmm let me think.\\n\\nWhy, he's probably chasing after the last cup of coffee in the office!\", additional_kwargs={}, response_metadata={}),\n",
|
||||
" HumanMessage(content='why is 42 always the answer?', additional_kwargs={}, response_metadata={}),\n",
|
||||
" AIMessage(content='Because it’s the only number that’s constantly right, even when it doesn’t add up!', additional_kwargs={}, response_metadata={}),\n",
|
||||
" HumanMessage(content='What is the difference between a computer and a machine?', additional_kwargs={}, response_metadata={})]"
|
||||
" HumanMessage(content='What did the cow say?', additional_kwargs={}, response_metadata={})]"
|
||||
]
|
||||
},
|
||||
"execution_count": 70,
|
||||
"execution_count": 12,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
@@ -565,7 +594,7 @@
|
||||
" AIMessage(\n",
|
||||
" \"Because it’s the only number that’s constantly right, even when it doesn’t add up!\"\n",
|
||||
" ),\n",
|
||||
" HumanMessage(\"What is the difference between a computer and a machine?\"),\n",
|
||||
" HumanMessage(\"What did the cow say?\"),\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"\n",
|
||||
@@ -610,34 +639,49 @@
|
||||
"The obvious downside of this approach is that latency starts to increase as the conversation history grows because of two reasons:\n",
|
||||
"\n",
|
||||
"1. As the conversation gets longer, more data may need to be fetched from whatever store your'e using to store the conversation history (if not storing it in memory).\n",
|
||||
"2. The pre-processing logic will end up doing a lot of redundant computation, repeating computation from previous steps of the conversation."
|
||||
"2. The pre-processing logic will end up doing a lot of redundant computation, repeating computation from previous steps of the conversation.\n",
|
||||
"\n",
|
||||
":::caution\n",
|
||||
"\n",
|
||||
"If you're using tools, remember to bind the tools to the model before adding a pre-processing step to it!\n",
|
||||
"\n",
|
||||
":::"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 73,
|
||||
"execution_count": 13,
|
||||
"id": "5537b001-a49c-4d12-b25d-4087890f49b4",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"AIMessage(content=\"Well, a computer is a machine that can think, while a machine is a computer that can't!\", additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 21, 'prompt_tokens': 96, 'total_tokens': 117, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-0f08b428-8eb8-4422-b6d0-3ac494c0b6fe-0', usage_metadata={'input_tokens': 96, 'output_tokens': 21, 'total_tokens': 117})"
|
||||
"AIMessage(content='', additional_kwargs={'tool_calls': [{'id': 'call_aYRmth57XGNqvZq3V5vn0Urg', 'function': {'arguments': '{}', 'name': 'what_did_the_cow_say'}, 'type': 'function'}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 16, 'prompt_tokens': 126, 'total_tokens': 142, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run-93b89a08-b8a1-4a7a-bedd-ab7e2ce47894-0', tool_calls=[{'name': 'what_did_the_cow_say', 'args': {}, 'id': 'call_aYRmth57XGNqvZq3V5vn0Urg', 'type': 'tool_call'}], usage_metadata={'input_tokens': 126, 'output_tokens': 16, 'total_tokens': 142})"
|
||||
]
|
||||
},
|
||||
"execution_count": 73,
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from langchain_core.tools import tool\n",
|
||||
"from langchain_openai import ChatOpenAI\n",
|
||||
"\n",
|
||||
"model = ChatOpenAI()\n",
|
||||
"\n",
|
||||
"# highlight-next-line\n",
|
||||
"model_with_preprocessor = message_processor | model\n",
|
||||
"\n",
|
||||
"@tool\n",
|
||||
"def what_did_the_cow_say() -> str:\n",
|
||||
" \"\"\"Check to see what the cow said.\"\"\"\n",
|
||||
" return \"foo\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"model_with_tools = model.bind_tools([what_did_the_cow_say])\n",
|
||||
"\n",
|
||||
"# highlight-next-line\n",
|
||||
"model_with_preprocessor = message_processor | model_with_tools\n",
|
||||
"\n",
|
||||
"# full_message_history in the previous code block.\n",
|
||||
"# We pass it explicity to the model_with_preprocesor for illustrative purposes.\n",
|
||||
@@ -646,6 +690,18 @@
|
||||
"model_with_preprocessor.invoke(full_message_history)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "aaa4e03a-0050-4f1d-bda1-530e387966bf",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"If you need to implement more efficient logic and want to use `RunnableWithMessageHistory` for now the way to achieve this\n",
|
||||
"is to subclass from [BaseChatMessageHistory](https://api.python.langchain.com/en/latest/chat_history/langchain_core.chat_history.BaseChatMessageHistory.html) and\n",
|
||||
"define appropriate logic for `add_messages` (that doesn't simply append the history, but instead re-writes it).\n",
|
||||
"\n",
|
||||
"Unless you have a good reason to implement this solution, you should instead use LangGraph,"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "84229e2e-a578-4b21-840a-814223406402",
|
||||
@@ -659,7 +715,7 @@
|
||||
"\n",
|
||||
"You can create a pre-built agent using: [create_react_agent](https://langchain-ai.github.io/langgraph/reference/prebuilt/#create_react_agent).\n",
|
||||
"\n",
|
||||
"To add memory pre-processing to the agent\n",
|
||||
"To add memory pre-processing to the agent, you can do the following:\n",
|
||||
"\n",
|
||||
"```python\n",
|
||||
"\n",
|
||||
@@ -673,7 +729,7 @@
|
||||
"# highlight-end \n",
|
||||
"\n",
|
||||
"app = create_react_agent(\n",
|
||||
" model, \n",
|
||||
" model,\n",
|
||||
" tools=[get_user_age], \n",
|
||||
" checkpointer=memory,\n",
|
||||
" # highlight-next-line\n",
|
||||
@@ -684,12 +740,12 @@
|
||||
"\n",
|
||||
"```\n",
|
||||
"\n",
|
||||
"Pre-built react-agent"
|
||||
"At each turn of the conversation, "
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 74,
|
||||
"execution_count": 14,
|
||||
"id": "f671db87-8f01-453e-81fd-4e603140a512",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
@@ -702,8 +758,8 @@
|
||||
"hi! I'm bob. What is my age?\n",
|
||||
"==================================\u001b[1m Ai Message \u001b[0m==================================\n",
|
||||
"Tool Calls:\n",
|
||||
" get_user_age (call_BVUwjmlAebA36jK6WFOtDWfi)\n",
|
||||
" Call ID: call_BVUwjmlAebA36jK6WFOtDWfi\n",
|
||||
" get_user_age (call_kTEpBUbRFbKE3DZolG9tFrgD)\n",
|
||||
" Call ID: call_kTEpBUbRFbKE3DZolG9tFrgD\n",
|
||||
" Args:\n",
|
||||
" name: bob\n",
|
||||
"=================================\u001b[1m Tool Message \u001b[0m=================================\n",
|
||||
@@ -783,6 +839,19 @@
|
||||
" event[\"messages\"][-1].pretty_print()"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "7a231ade-9f33-4ff8-9a62-20be3fc159b6",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### ConversationSummaryMemory / ConversationSummaryBufferMemory\n",
|
||||
"\n",
|
||||
"It’s essential to summarize conversations efficiently to prevent growing latency as the conversation history grows.\n",
|
||||
"\n",
|
||||
"Please follow the guide [how to add summary of the conversation history](https://langchain-ai.github.io/langgraph/how-tos/memory/add-summary-conversation-history/) to see learn how to\n",
|
||||
"handle conversation summarization efficiently with LangGraph."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "b2717810",
|
||||
@@ -799,13 +868,13 @@
|
||||
"\n",
|
||||
"Add persistence with simple LCEL (favor langgraph for more complex use cases):\n",
|
||||
"\n",
|
||||
"* [How to add message history](https://python.langchain.com/docs/how_to/message_history/)\n",
|
||||
"* [How to add message history](/docs/how_to/message_history/)\n",
|
||||
"\n",
|
||||
"Working with message history:\n",
|
||||
"\n",
|
||||
"* [How to trim messages](https://python.langchain.com/docs/how_to/trim_messages)\n",
|
||||
"* [How to filter messages](https://python.langchain.com/docs/how_to/filter_messages/)\n",
|
||||
"* [How to merge message runs](https://python.langchain.com/docs/how_to/merge_message_runs/)"
|
||||
"* [How to trim messages](/docs/how_to/trim_messages)\n",
|
||||
"* [How to filter messages](/docs/how_to/filter_messages/)\n",
|
||||
"* [How to merge message runs](/docs/how_to/merge_message_runs/)"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user