网站搭建好后被移动宽带屏蔽怎么办,嵌入式硬件开发,vue做的博客网站,可以搜任何网站的浏览器文章目录前言一、如何实现多轮对话存储二、FileChatMessageHistory的使用方法1.代码#xff08;为了演示多轮对话#xff0c;使用了函数#xff09;2. 运行结果2.1 可以看到#xff0c;AI可以通过历史记录回答原本不知道的问题2.2 看看对话记录怎么存储的#xff08;就是按…文章目录前言一、如何实现多轮对话存储二、FileChatMessageHistory的使用方法1.代码为了演示多轮对话使用了函数2. 运行结果2.1 可以看到AI可以通过历史记录回答原本不知道的问题2.2 看看对话记录怎么存储的就是按照固定格式以json格式存储三、历史记录截留实现方式举个例子总结前言提示承上启下系列文章通过前言会议一下上篇章内容引入本文内容从05.AI应用搭建–langchain输出解析器后基本介绍完一个简单AI应用的基本流程。但是大家很容易发现前面的内容更多是一问一答形式无法实现追问那么对于这种场景应该如何解决呢立刻有人想到既然可以拼接强化AI和user的提示词内容那我直接将AI的输出和用户的历史提问记录下来然后拼接进每次的提问不就可以了那么恭喜你已经掌握了多轮对话的实现基础。一、如何实现多轮对话存储通过一段代码简单理解下基础原理# 构造提示词。其中MessagesPlaceholder是消息占位符它的作用是可以动态插入历史对话记录 MessagesPlaceholder的消息结构如下 [ (human, 你好我叫小明), (system, 你好小明有什么我能帮助你的吗。), (human, 我最喜欢红色帮我选一种适合圣诞节的礼物), (system, 圣诞帽), ] fromlangchain_community.chat_modelsimportMessagesPlaceholder#1、构造提示词模板可以看出和之前讲的没什么不同只是加了个MessagesPlaceholder按照其数据结构很容易理解就是将历史对话拼接进了提示词中。# variable_nameconversation这就是声明历史对话通过哪个参数传入提示词promptChatPromptTemplate.from_messages([(system,你是一个友好的助手根据对话历史回答问题。),MessagesPlaceholder(variable_nameconversation,optionalTrue),# 核心动态插入对话历史,其中optional 默认 False设为 True 则占位符无内容时不会报错(human,{input}),# 当前用户输入])# 2、 模拟对话历史可来自用户与AI的交互记录conversation_history[HumanMessage(content你好我叫小明),AIMessage(content你好小明有什么我能帮助你的吗),HumanMessage(content我忘记我叫什么了),]# 3. 构造链调用模型。可以看到传入历史记录和原来的填入用户输入没什么不同chainprompt|llm responsechain.invoke({conversation:conversation_history,# 填充占位符input:提醒我一下我的名字# 当前输入})#从输出结果可以看出来大模型从历史对话中找到了自己不知道的内容并回答了用户的问题print(response.content)# 输出示例你的名字是小明呀从这个例子可以看出1、想要传入历史对话只需要在通过MessagesPlaceholder在提示词内拼接历史对话记录即可2、历史对话记录存储时需要记录对话的角色信息如system、human等3、大模型会从历史对话记录中获取信息回答用户提问但是上面的例子有个大问题对话记录存在内存里的服务重启对话记录就清空了若要实现大型、长期的对话应用这肯定不行。有无办法想数据库一样将数据存在本地/服务器上要用的时候去获取出来 有的可以用FileChatMessageHistory、RedisChatMessageHistory将记录存储到文件或Redis内本文只讲FileChatMessageHistoryRedisChatMessageHistory的原理差不多只是调用Redis的方法存放在不同位置而已可自行补充二、FileChatMessageHistory的使用方法若相同代码import时报错可能是langchain的版本不一致导致的我使用的版本如下pip install-i https://mirrors.aliyun.com/pypi/simple/langchain0.2.10langchain-openai langchain-community python-dotenv1.代码为了演示多轮对话使用了函数importosfromdotenvimportload_dotenv# 补充加载环境变量fromlangchain_openaiimportChatOpenAIfromlangchain_core.messagesimportHumanMessage,AIMessage,SystemMessagefromlangchain_community.chat_message_historiesimportFileChatMessageHistoryfromlangchain.memoryimportConversationBufferMemory# 加载.env文件国内用户必加否则API Key获取不到load_dotenv()# 大模型配置MODULE_API_KEYos.getenv(DASHSCOPE_API_KEY)MODULE_BASE_URLhttps://dashscope.aliyuncs.com/compatible-mode/v1MODULE_NAMEqwen-plus# 1. 初始化Qwen-plus模型 definit_qwen_plus_cn():returnChatOpenAI(api_keyMODULE_API_KEY,modelMODULE_NAME,base_urlMODULE_BASE_URL,temperature0.6,max_tokens2048,request_timeout30,# 补充国内网络超时配置避免卡死max_retries2# 补充失败重试适配国内网络波动)# 2. 本地文件存储 deffile_based_chat_demo():try:clientinit_qwen_plus_cn()exceptValueErrorase:print(f初始化失败{e})return# 按用户ID分文件存储国内合规user_iduser_001history_filef./chat_history/{user_id}_qwen_history.jsonos.makedirs(./chat_history,exist_okTrue)# 初始化文件存储 内存管理。message_history可简单理解为存储得对话内容message_historyFileChatMessageHistory(file_pathhistory_file)# ConversationBufferMemory 用于管理历史对话记录 前提ConversationBufferMemory存储的是json格式的数据所以数据的存储和获取都是用key进行操作 chat_memory消息存储在底层存储介质的位置 memory_key 该历史记录对应的key值 input_key : 用户输入内容的key值 output_keyAI输出内容的key值 memoryConversationBufferMemory(chat_memorymessage_history,return_messagesTrue,memory_keychat_history,# 关键与load_memory_variables的键名对齐input_keyhuman_input,# 关键与save_context的inputs键名对齐output_keyai_output# 关键与save_context的outputs键名对齐)print( 【国内版】Qwen-plus 文件存储对话 Demo )print(输入 退出 结束对话输入内容会本地保存)whileTrue:queryinput(\n请输入你的问题)ifquery.strip()in[退出,exit,quit]:print(f对话结束历史已保存至{history_file})breakifnotquery.strip():# 处理空输入避免调用空字符串print(输入不能为空请重新输入)continue# 加载历史消息load_memory_variables方法获取内存里的历史对话记录通过chat_history是对应的历史记录的key值。通过这个可以精准获取指定文件里的内容history_msgsmemory.load_memory_variables({})[chat_history]# 构造国内合规的系统提示词system_msgSystemMessage(content 你是通义千问Qwen-plus严格遵守中国法律法规拒绝回答敏感问题。 回答简洁、专业符合国内用户的使用习惯禁止输出无关内容。 )# 拼接上下文系统消息 历史 当前输入。*history_msgs就是把history_msgs解包。简单理解就是就列表里的每个元素取出来放在新的列表current_context里即两个列表的合并current_context[system_msg,*history_msgs,HumanMessage(contentquery)]# 调用模型try:responseclient.invoke(current_context)# 关键兼容Qwen-plus的返回格式可能是字符串/AIMessageifisinstance(response,str):ai_contentresponseelse:ai_contentresponse.contentexceptExceptionase:print(f模型调用失败{str(e)})continue# 保存历史键名与memory配置完全对齐。这一步会向文件内写入这轮AI中每轮一般包含用户提问ai回答对话数据memory.save_context(inputs{human_input:query},outputs{ai_output:ai_content})print(f千问回答{ai_content})if__name____main__:file_based_chat_demo()2. 运行结果2.1 可以看到AI可以通过历史记录回答原本不知道的问题2.2 看看对话记录怎么存储的就是按照固定格式以json格式存储{type:human,data:{content:你好我叫什么名字,additional_kwargs:{},response_metadata:{},type:human,name:null,id:null,example:false}},{type:ai,data:{content:你好我无法知道你的名字呢。你可以告诉我你的名字我会尊重并礼貌地与你交流。,additional_kwargs:{},response_metadata:{},type:ai,name:null,id:null,example:false,tool_calls:[],invalid_tool_calls:[],usage_metadata:null}},{type:human,data:{content:我叫幽奇男100岁请你记住我,additional_kwargs:{},response_metadata:{},type:human,name:null,id:null,example:false}},{type:ai,data:{content:你好幽奇虽然你说100岁但依然精神矍铄、童心未泯真让人佩服我会记住你的名字也感谢你的信任。有什么问题或需要帮助随时告诉我哦,additional_kwargs:{},response_metadata:{},type:ai,name:null,id:null,example:false,tool_calls:[],invalid_tool_calls:[],usage_metadata:null}},{type:human,data:{content:你好我叫什么名字,additional_kwargs:{},response_metadata:{},type:human,name:null,id:null,example:false}},{type:ai,data:{content:你好你叫幽奇。很高兴再次见到你有什么我可以帮你的吗,additional_kwargs:{},response_metadata:{},type:ai,name:null,id:null,example:false,tool_calls:[],invalid_tool_calls:[],usage_metadata:null}},三、历史记录截留每次访问携带历史记录问AI实现了多轮对话但是带来了个新问题token浪费随着对话论述增多将浪费大量token所以特定场景如长期的多轮对话需要现在最多取多少轮的历史记录或最长token实现方式举个例子# 自己实现个函数截留历史记录这里面的3就是只截留最近的3轮对话deftruncate_chat_history(chat_history:FileChatMessageHistory,max_rounds:int3):all_messageschat_history.messages keep_count2*max_roundsiflen(all_messages)keep_count:#接取最近的6条数据即3轮truncated_messagesall_messages[-keep_count:]#清除历史数据chat_history.clear()formsgintruncated_messages:chat_history.add_message(msg)returnlen(chat_history.messages)总结1、实现多轮对话的基础在于存储历史数据2、存储历史数据的方法可用MessagesPlaceholder自己实现存储过程也可以用FileChatMessageHistory自动化管理历史记录3、为了防止多轮对话历史记录太长导致大量浪费token可以截留历史记录