让大模型保存对话上下文

使用过大模型的都对token这个概念不陌生,token是大模型的基本单位,每个token都有一个对应的id,大模型的输入和输出都是由token组成的。 一次交互中,大模型可以支持越多的token数量往往意味大模型的能力越强(当然,这个不是绝对的)。下面,我们介绍一种保存大模型上下文的最基本方法。

使用 LLMChain / ConversationChain 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import os
from langchain_openai import ChatOpenAI
from langchain.chains import LLMChain
from langchain.memory import ConversationBufferMemory
from langchain_core.messages import SystemMessage
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.prompts.chat import (
    ChatPromptTemplate,
    HumanMessagePromptTemplate,
    MessagesPlaceholder,
)

prompt = ChatPromptTemplate(
    [
        MessagesPlaceholder(variable_name="chat_history"),
        HumanMessagePromptTemplate.from_template("{text}"),
    ]
)
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)


OPENAIKEY = os.getenv("OPENAI_API_KEY") # 建议更名

llmparam = ChatOpenAI(
model="gpt-4o",
temperature=0,
max_tokens=None,
timeout=30, # 建议设置合理超时
max_retries=2,
api_key=OPENAIKEY,
base_url="https://api.openai-proxy.org/v1",
)


legacy_chain = LLMChain(
    llm=llmparam,
    prompt=prompt,
    memory=memory,
)

print(legacy_result)

print(legacy_result["text"])
legacy_result = legacy_chain.invoke({"text": "my age is 23"})
print(legacy_result)

print(legacy_result["text"])
legacy_result = legacy_chain.invoke({"text": "what was my name"})
print(legacy_result["text"])
legacy_result = legacy_chain.invoke({"text": "what was my age ? "})
print(legacy_result["text"])
legacy_result = legacy_chain.invoke({"text": "what was my father's name ?"})
print(legacy_result["text"])

输出:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "text": "Hi Bob! Nice to meet you. How can I assist you today? 😊",
  "chat_history": [
    {
      "type": "HumanMessage",
      "content": "my name is bob",
      "additional_kwargs": {},
      "response_metadata": {}
    },
    {
      "type": "AIMessage",
      "content": "Hi Bob! Nice to meet you. How can I assist you today? 😊",
      "additional_kwargs": {},
      "response_metadata": {}
    }
  ]
}

Hi Bob! Nice to meet you. How can I assist you today? 😊

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
  "text": "That's awesome, Bob! 23 is a great age—you're in the prime of exploring life and chasing your dreams. Is there anything specific you'd like to talk about or work on today? 😊",
  "chat_history": [
    {
      "type": "HumanMessage",
      "content": "my name is bob",
      "additional_kwargs": {},
      "response_metadata": {}
    },
    {
      "type": "AIMessage",
      "content": "Hi Bob! Nice to meet you. How can I assist you today? 😊",
      "additional_kwargs": {},
      "response_metadata": {}
    },
    {
      "type": "HumanMessage",
      "content": "my age is 23",
      "additional_kwargs": {},
      "response_metadata": {}
    },
    {
      "type": "AIMessage",
      "content": "That's awesome, Bob! 23 is a great age—you're in the prime of exploring life and chasing your dreams. Is there anything specific you'd like to talk about or work on today? 😊",
      "additional_kwargs": {},
      "response_metadata": {}
    }
  ]
}

That’s awesome, Bob! 23 is a great age—you’re in the prime of exploring life and chasing your dreams. Is there anything specific you’d like to talk about or work on today? 😊 Your name is Bob! 😊 Your age is 23! 😊 You haven’t mentioned your father’s name yet, Bob! Feel free to share if you’d like me to know. 😊

以上方式是比较简单的保存对话历史的方式,缺点是,只能在同一个对话中保存上下文,不能跨对话保存上下文。如果需要跨对话保存上下文,需要高级的LangGraph方式。

使用 langgraph 实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import uuid
import os
from IPython.display import Image, display
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
from langgraph.graph import START, MessagesState, StateGraph

# Define a new graph
workflow = StateGraph(state_schema=MessagesState)

# Define a chat model
model = ChatOpenAI(
model="gpt-4o",
temperature=0,
max_tokens=None,
timeout=30, # 建议设置合理超时
max_retries=2,
api_key=OPENAIKEY,
base_url="https://api.openai-proxy.org/v1",
)

OPENAIKEY = os.getenv("OPENAI_API_KEY")
# Define the function that calls the model
def call_model(state: MessagesState):
    response = model.invoke(state["messages"])
    # We return a list, because this will get added to the existing list
    return {"messages": response}


# Define the two nodes we will cycle between
workflow.add_edge(START, "model")
workflow.add_node("model", call_model)


# Adding memory is straight forward in langgraph!
memory = MemorySaver()

app = workflow.compile(
    checkpointer=memory
)


# The thread id is a unique key that identifies
# this particular conversation.
# We'll just generate a random uuid here.
# This enables a single application to manage conversations among multiple users.
thread_id = uuid.uuid4()
config = {"configurable": {"thread_id": thread_id}}

input_message = HumanMessage(content="hi! I'm bob")
for event in app.stream({"messages": [input_message]}, config, stream_mode="values"):
    event["messages"][-1].pretty_print()

# Here, let's confirm that the AI remembers our name!
input_message = HumanMessage(content="what was my name?")
for event in app.stream({"messages": [input_message]}, config, stream_mode="values"):
    event["messages"][-1].pretty_print()

输出:

================================ Human Message =================================

hi! I’m bob ================================== Ai Message ==================================

Hi Bob! 👋 How’s it going? ================================ Human Message =================================

what was my name? ================================== Ai Message ==================================

Your name is Bob! 😊

LangGraph是一个基于图这种数据结构实现的,用于构建复杂的应用程序的框架,它可以帮助开发者构建可扩展、可维护的应用程序。它的出现 大大增强的智能体的能力,当然,也正是因为它功能强大,使用起来也比较复杂。想学习的朋友,可以参考官方文档: https://www.langchain.com/langgraph