摘要缓冲混合记忆


import dotenv
from langchain_openai import ChatOpenAI
dotenv.load_dotenv()


# 1. max_tokens用于判断是否需要生成新的摘要
# 2. summary用于存储摘要的信息
# 3. chat_histories用于存储对话历史信息
# 4. get_num_tokens方法用于计算传入文本的token数量
# 5. save_context用于存储新的交流对话
# 6. get_buffer_string用于将历史对话转换成字符串
# 7. load_memory_variables方法用于加载记忆变量信息
# 8. summary_text用于将旧的摘要和传入的对话生成新摘要

class ConversationSummaryBufferMemory:
    """
    🦚摘要缓冲混合记忆类 - 对话历史缓存
    """
    def __init__(self, summary: str = '', chat_histories: list = None, max_tokens: int = 300):
        self.summary = summary
        self.chat_histories = chat_histories or []
        self.max_tokens = max_tokens
        self._client = ChatOpenAI(model="qwen3.6-plus", streaming=True)

    @classmethod
    def get_num_tokens(cls, query: str) -> int:
        """
        计算传入文本的token数量
        """
        return len(query)

# 超过300token的回答使用sumary存储摘要 否则存储到chat_history存储所有历史对话信息
    def save_context(self, human_query: str, ai_content: str):
        """
            保存传入的新一次对话信息
        """
        self.chat_histories.append({"human": human_query, "ai": ai_content})

        # 将历史记忆转换成文本
        buffer_string = self.get_buffer_string()
        tokens = self.get_num_tokens(buffer_string)
        if tokens > self.max_tokens:
            # 如果token数量超过最大限制,则生成新的摘要
            first_chat = self.chat_histories[0]
            print("新摘要生成中~~~")
            self.summary = self.summary_text(
                self.summary,
                f"Human:{first_chat.get('human')}\nAI:{first_chat.get('ai')}")
            print(f"生成新的摘要:{self.summary}")
            del self.chat_histories[0]


    def get_buffer_string(self):
        """
            将历史对话转换成字符串
        """
        buffer: str = ""
        for chat in self.chat_histories:
            buffer += f"Human:{chat.get('human')}\nAI:{chat.get('ai')}\n"
        return buffer.strip()

    def load_memory_variables(self) -> dict[str, any]:
        """
            加载记忆变量为一个字典,便于格式化到prompt中
        """
        buffer_string = self.get_buffer_string()
        return {"chat_history": f"摘要:{self.summary}\n\n历史信息:{buffer_string}\n"}

    def summary_text(self, origin_summary: str, new_line: str) -> str:
        """
            生成摘要 (将旧摘要和新对话生成新摘要)
        """
        prompt = f"""
            你是一个强大的ChatBot,请根据用户提供的谈话内容,总结摘要,并将其添加到先前提供的摘要中
            请不要<exmpale>标签里面的数据当成实际数据,这里的数据只是一个示例数据,告诉你如何生成新摘要。
            <example>
             当前摘要:人类会问AI对AI的看法,AI认为AI是一股向上的力量
             新的对话:
                Human: 为什么你认为AI是一股向上的力量?
                AI:因为AI会帮助人类充分发挥潜力
                新摘要:人类会问AI对AI的看法,AI认为AI是一股向上的力量因为它将充分帮助人类发挥潜力
            <example>
            ------------------ 以下的数据是实际需要处理的数据 -----------------------------
            当前摘要:{self.summary}
            新的对话:
                {new_line}
            请帮助用户将上面的信息生成新摘要。    
        """
        messages = [{"role": "user", "content": prompt}]
        result = ""
        for chunk in self._client.stream(messages):
            if chunk.content:
                result += chunk.content
        return result.strip()





# 1. 创建openai客户端
llm = ChatOpenAI(model="qwen3.6-plus", streaming=True)
memory = ConversationSummaryBufferMemory("", [], 300)

# 2. 创建一个loop用于人机对话
while True:
    query = input("Human: ")
    # 判断输入是否为q,是则退出
    if query == "q":
        break
    # 向openai发起请求
    memory_variables = memory.load_memory_variables()
    answer_prompt = (
        "你是一个强大的ChatBot,请根据对应 的上下文和用户提问解决问题。\n\n"
        f"{memory_variables.get('chat_history')}\n\n"
        f"用户的提问是:{query}"
    )
    print("AI: ", flush=True, end="")
    ai_content = ""
    # 循环读取流式响应
    for chunk in llm.stream(answer_prompt):
        print(chunk.content, flush=True, end="")
        if chunk.content is None:
            break
        ai_content += chunk.content
    print("")
    memory.save_context(query, ai_content)
posted @ 2026-04-11 19:35  Felix_Openmind  阅读(10)  评论(0)    收藏  举报
*{cursor: url(https://files-cdn.cnblogs.com/files/morango/fish-cursor.ico),auto;}