%%capture --no-stderr
%pip install -U langchain_openai langgraph langchain_core
import os, getpass
def _set_env(var: str):
if not os.environ.get(var):
os.environ[var] = getpass.getpass(f"{var}: ")
_set_env("LANGSMITH_API_KEY")
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_PROJECT"] = "langchain-academy"
import uuid
from langgraph.store.memory import InMemoryStore
in_memory_store = InMemoryStore()
# Namespace for the memory to save
user_id = "1"
namespace_for_memory = (user_id, "memories")
# Save a memory to namespace as key and value
key = str(uuid.uuid4())
# The value needs to be a dictionary
value = {"food_preference" : "I like pizza"}
# Save the memory
in_memory_store.put(namespace_for_memory, key, value)
我们使用search方法通过namespace
从存储中检索对象。
该方法会返回一个列表。
# Search
memories = in_memory_store.search(namespace_for_memory)
type(memories)
list
# Metatdata
memories[0].dict()
{'value': {'food_preference': 'I like pizza'}, 'key': 'a754b8c5-e8b7-40ec-834b-c426a9a7c7cc', 'namespace': ['1', 'memories'], 'created_at': '2024-11-04T22:48:16.727572+00:00', 'updated_at': '2024-11-04T22:48:16.727574+00:00'}
# The key, value
print(memories[0].key, memories[0].value)
a754b8c5-e8b7-40ec-834b-c426a9a7c7cc {'food_preference': 'I like pizza'}
我们也可以通过 get 方法,根据 namespace
和 key
来检索对象。
# Get the memory by namespace and key
memory = in_memory_store.get(namespace_for_memory, key)
memory.dict()
{'value': {'food_preference': 'I like pizza'}, 'key': 'a754b8c5-e8b7-40ec-834b-c426a9a7c7cc', 'namespace': ['1', 'memories'], 'created_at': '2024-11-04T22:48:16.727572+00:00', 'updated_at': '2024-11-04T22:48:16.727574+00:00'}
_set_env("OPENAI_API_KEY")
对于short-term memory
(短期记忆),我们将使用检查点工具。
更多关于检查点工具的详细信息请参阅模块2和我们的概念文档,以下是其主要功能总结:
- 将每个步骤的图状态写入线程
- 在线程中持久化保存聊天历史记录
- 允许图形在执行过程中被中断,并可从线程中的任意步骤恢复
而对于long-term memory
(长期记忆),我们将使用前文介绍的LangGraph存储。
# Chat model
from langchain_openai import ChatOpenAI
# Initialize the LLM
model = ChatOpenAI(model="gpt-4o", temperature=0)
聊天记录将通过检查点机制保存至短期记忆。
聊天机器人会对聊天记录进行反思。
随后它将创建并保存一段记忆至 LangGraph 存储库。
该记忆可在未来的聊天会话中调用,用于个性化定制聊天机器人的响应。
from IPython.display import Image, display
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.store.base import BaseStore
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.runnables.config import RunnableConfig
# Chatbot instruction
MODEL_SYSTEM_MESSAGE = """You are a helpful assistant with memory that provides information about the user.
If you have memory for this user, use it to personalize your responses.
Here is the memory (it may be empty): {memory}"""
# Create new memory from the chat history and any existing memory
CREATE_MEMORY_INSTRUCTION = """"You are collecting information about the user to personalize your responses.
CURRENT USER INFORMATION:
{memory}
INSTRUCTIONS:
1. Review the chat history below carefully
2. Identify new information about the user, such as:
- Personal details (name, location)
- Preferences (likes, dislikes)
- Interests and hobbies
- Past experiences
- Goals or future plans
3. Merge any new information with existing memory
4. Format the memory as a clear, bulleted list
5. If new information conflicts with existing memory, keep the most recent version
Remember: Only include factual information directly stated by the user. Do not make assumptions or inferences.
Based on the chat history below, please update the user information:"""
def call_model(state: MessagesState, config: RunnableConfig, store: BaseStore):
"""Load memory from the store and use it to personalize the chatbot's response."""
# Get the user ID from the config
user_id = config["configurable"]["user_id"]
# Retrieve memory from the store
namespace = ("memory", user_id)
key = "user_memory"
existing_memory = store.get(namespace, key)
# Extract the actual memory content if it exists and add a prefix
if existing_memory:
# Value is a dictionary with a memory key
existing_memory_content = existing_memory.value.get('memory')
else:
existing_memory_content = "No existing memory found."
# Format the memory in the system prompt
system_msg = MODEL_SYSTEM_MESSAGE.format(memory=existing_memory_content)
# Respond using memory as well as the chat history
response = model.invoke([SystemMessage(content=system_msg)]+state["messages"])
return {"messages": response}
def write_memory(state: MessagesState, config: RunnableConfig, store: BaseStore):
"""Reflect on the chat history and save a memory to the store."""
# Get the user ID from the config
user_id = config["configurable"]["user_id"]
# Retrieve existing memory from the store
namespace = ("memory", user_id)
existing_memory = store.get(namespace, "user_memory")
# Extract the memory
if existing_memory:
existing_memory_content = existing_memory.value.get('memory')
else:
existing_memory_content = "No existing memory found."
# Format the memory in the system prompt
system_msg = CREATE_MEMORY_INSTRUCTION.format(memory=existing_memory_content)
new_memory = model.invoke([SystemMessage(content=system_msg)]+state['messages'])
# Overwrite the existing memory in the store
key = "user_memory"
# Write value as a dictionary with a memory key
store.put(namespace, key, {"memory": new_memory.content})
# Define the graph
builder = StateGraph(MessagesState)
builder.add_node("call_model", call_model)
builder.add_node("write_memory", write_memory)
builder.add_edge(START, "call_model")
builder.add_edge("call_model", "write_memory")
builder.add_edge("write_memory", END)
# Store for long-term (across-thread) memory
across_thread_memory = InMemoryStore()
# Checkpointer for short-term (within-thread) memory
within_thread_memory = MemorySaver()
# Compile the graph with the checkpointer fir and store
graph = builder.compile(checkpointer=within_thread_memory, store=across_thread_memory)
# View
display(Image(graph.get_graph(xray=1).draw_mermaid_png()))
当我们与聊天机器人交互时,需要提供两个要素:
短期记忆(线程内)
:用于持久化聊天历史的线程ID
。长期记忆(跨线程)
:通过用户ID
为用户划分长期记忆的命名空间。
下面我们通过实际场景看看这两者如何协同工作。
# We supply a thread ID for short-term (within-thread) memory
# We supply a user ID for long-term (across-thread) memory
config = {"configurable": {"thread_id": "1", "user_id": "1"}}
# User input
input_messages = [HumanMessage(content="Hi, my name is Lance")]
# Run the graph
for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"):
chunk["messages"][-1].pretty_print()
================================ Human Message ================================= Hi, my name is Lance ================================== Ai Message ================================== Hello, Lance! It's nice to meet you. How can I assist you today?
# User input
input_messages = [HumanMessage(content="I like to bike around San Francisco")]
# Run the graph
for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"):
chunk["messages"][-1].pretty_print()
================================ Human Message ================================= I like to bike around San Francisco ================================== Ai Message ================================== That sounds like a great way to explore the city, Lance! San Francisco has some beautiful routes and views. Do you have a favorite trail or area you like to bike in?
我们正在使用 MemorySaver
检查点机制来实现线程内内存管理。
该功能会将聊天记录保存至当前线程。
我们可以查看已保存至线程的聊天历史记录。
thread = {"configurable": {"thread_id": "1"}}
state = graph.get_state(thread).values
for m in state["messages"]:
m.pretty_print()
================================ Human Message ================================= Hi, my name is Lance ================================== Ai Message ================================== Hello, Lance! It's nice to meet you. How can I assist you today? ================================ Human Message ================================= I like to bike around San Francisco ================================== Ai Message ================================== That sounds like a great way to explore the city, Lance! San Francisco has some beautiful routes and views. Do you have a favorite trail or area you like to bike in?
请注意我们之前使用存储库编译了该图:
across_thread_memory = InMemoryStore()
同时,我们在图中添加了一个节点(write_memory
),该节点会记录聊天历史并将记忆保存至存储库。
现在我们可以验证该记忆是否已成功存入存储库。
# Namespace for the memory to save
user_id = "1"
namespace = ("memory", user_id)
existing_memory = across_thread_memory.get(namespace, "user_memory")
existing_memory.dict()
{'value': {'memory': "**Updated User Information:**\n- User's name is Lance.\n- Likes to bike around San Francisco."}, 'key': 'user_memory', 'namespace': ['memory', '1'], 'created_at': '2024-11-05T00:12:17.383918+00:00', 'updated_at': '2024-11-05T00:12:25.469528+00:00'}
现在,让我们用相同的用户ID启动一个新会话。
我们将看到聊天机器人记住了用户资料,并据此提供个性化的回复。
# We supply a user ID for across-thread memory as well as a new thread ID
config = {"configurable": {"thread_id": "2", "user_id": "1"}}
# User input
input_messages = [HumanMessage(content="Hi! Where would you recommend that I go biking?")]
# Run the graph
for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"):
chunk["messages"][-1].pretty_print()
================================ Human Message ================================= Hi! Where would you recommend that I go biking? ================================== Ai Message ================================== Hi Lance! Since you enjoy biking around San Francisco, there are some fantastic routes you might love. Here are a few recommendations: 1. **Golden Gate Park**: This is a classic choice with plenty of trails and beautiful scenery. You can explore the park's many attractions, like the Conservatory of Flowers and the Japanese Tea Garden. 2. **The Embarcadero**: A ride along the Embarcadero offers stunning views of the Bay Bridge and the waterfront. It's a great way to experience the city's vibrant atmosphere. 3. **Marin Headlands**: If you're up for a bit of a challenge, biking across the Golden Gate Bridge to the Marin Headlands offers breathtaking views of the city and the Pacific Ocean. 4. **Presidio**: This area has a network of trails with varying difficulty levels, and you can enjoy views of the Golden Gate Bridge and the bay. 5. **Twin Peaks**: For a more challenging ride, head up to Twin Peaks. The climb is worth it for the panoramic views of the city. Let me know if you want more details on any of these routes!
# User input
input_messages = [HumanMessage(content="Great, are there any bakeries nearby that I can check out? I like a croissant after biking.")]
# Run the graph
for chunk in graph.stream({"messages": input_messages}, config, stream_mode="values"):
chunk["messages"][-1].pretty_print()
================================ Human Message ================================= Great, are there any bakeries nearby that I can check out? I like a croissant after biking. ================================== Ai Message ================================== Absolutely, Lance! Here are a few bakeries in San Francisco where you can enjoy a delicious croissant after your ride: 1. **Tartine Bakery**: Located in the Mission District, Tartine is famous for its pastries, and their croissants are a must-try. 2. **Arsicault Bakery**: This bakery in the Richmond District has been praised for its buttery, flaky croissants. It's a bit of a detour, but worth it! 3. **b. Patisserie**: Situated in Lower Pacific Heights, b. Patisserie offers a variety of pastries, and their croissants are particularly popular. 4. **Le Marais Bakery**: With locations in the Marina and Castro, Le Marais offers a charming French bakery experience with excellent croissants. 5. **Neighbor Bakehouse**: Located in the Dogpatch, this bakery is known for its creative pastries, including some fantastic croissants. These spots should provide a delightful treat after your biking adventures. Enjoy your ride and your croissant!
在LangSmith中查看追踪记录¶
我们可以看到,记忆内容如预期那样从存储中检索出来,并作为系统提示的一部分提供:
https://smith.langchain.com/public/10268d64-82ff-434e-ac02-4afa5cc15432/r
工作室(Studio)¶
我们还可以在工作室中与聊天机器人进行交互。
# Getting Started with PyTorch
## Installation
To install PyTorch, run the following command:
```bash
pip install torch torchvision
Verifying Installation¶
After installation, verify it by running:
import torch
print(torch.__version__)
Basic Tensors¶
Tensors are the central data structure in PyTorch. Here's how to create a simple tensor:
x = torch.tensor([1, 2, 3])
print(x)
Tensor Operations¶
Basic operations include:
- Addition:
torch.add(x, y)
- Matrix multiplication:
torch.mm(x, y)
- Reshaping:
x.view(2, 3)
我明白了,以下是严格遵循您要求的 Markdown 格式中文翻译:
```markdown
# PyTorch 入门指南
## 安装
通过以下命令安装 PyTorch:
```bash
pip install torch torchvision
验证安装¶
安装完成后,运行以下代码验证:
import torch
print(torch.__version__)
基础张量¶
张量是 PyTorch 的核心数据结构。创建简单张量的方法如下:
x = torch.tensor([1, 2, 3])
print(x)
张量运算¶
基础运算包括:
- 加法:
torch.add(x, y)
- 矩阵乘法:
torch.mm(x, y)
- 形状变换:
x.view(2, 3)