目标
我们将建立一个带有对话历史的聊天机器人。
以下是我们将要使用的一些组件:
聊天模型(Chat Models):聊天机器人的界面是基于消息传递而不是原始文本,因此它更适合使用聊天模型而不是文本型的 LLM。
提示模板(Prompt Templates):这些模板简化了组装提示的过程,可以结合默认消息、用户输入、聊天历史以及(可选的)额外检索到的上下文。
聊天历史(Chat History):聊天历史允许聊天机器人“记住”过去的交互,并在回应后续问题时考虑这些历史。
使用 LangSmith 调试和跟踪你的应用程序(非必须 )。
聊天历史 在[Vol][2]中,我们使用了一个 messages[]来保存和传递消息,它是这个样子
1 2 3 4 5 [ SystemMessage(content="Translate the following from English into Italian" ), HumanMessage(content="hi!" ), ... ]
其实,随着对话的增长,我们可以把AI消息和我们自己的消息一起添加到这个列表里
1 2 3 4 5 6 7 8 9 10 11 [ SystemMessage(content="Translate the following from English into Italian" ), HumanMessage(content="hi!" ), AIMessage(content="..." ) HumanMessage(content="..." ), AIMessage(content="..." ) HumanMessage(content="..." ), AIMessage(content="..." ) HumanMessage(content="..." ), ... ]
上面[]的内容,就是对话历史…
我们先不看官方的例子,简单的事非得搞复杂…
我们先自己维护一下对话历史,感受一下最底层的对话历史逻辑~
这里我们用通义千问做演示
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 api_key = DASHSCOPE_API_KEY qwen_chat = ChatOpenAI( model_name="qwen-max" , openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1" , openai_api_key=api_key, ) parser = StrOutputParser() system_template = "你是一个AI助手。" sys_msg = SystemMessage(content=system_template) messages = [] messages.append(sys_msg) res = qwen_chat.invoke("hi,你好,我是粥~" ) print (res)messages.append(HumanMessage(content="hi,你好,我是粥~" )) messages.append(res) messages.append(HumanMessage(content="我是谁?" )) res = qwen_chat.invoke(messages) print (res.content)pass
在res = qwen_chat.invoke(messages) 调用前,对话历史是这样的
1 2 3 4 5 6 [ SystemMessage(content='你是一个AI助手。' ), HumanMessage(content='hi,你好,我是粥~' ), AIMessage(content='你好,粥~!很高兴能与你交流。有什么可以帮助你的吗?' , response_metadata={'token_usage' : {'completion_tokens' : 16 , 'prompt_tokens' : 15 , 'total_tokens' : 31 }, 'model_name' : 'qwen-max' , 'system_fingerprint' : None , 'finish_reason' : 'stop' , 'logprobs' : None }, id ='run-ae2d37f0-287f-4c37-a0cd-bc0a8cc2114f-0' ), HumanMessage(content='我是谁?' ) ]
AI最后的回答
可以看到,AI还记得我是粥,这个效果是因为我们在messages里有对话历史
1 content='你是卷儿,刚刚你自己介绍过了哦。如果有什么想聊的或者需要帮助的,尽管告诉我!' response_metadata={'token_usage' : {'completion_tokens' : 23 , 'prompt_tokens' : 54 , 'total_tokens' : 77 }, 'model_name' : 'qwen-max' , 'system_fingerprint' : None , 'finish_reason' : 'stop' , 'logprobs' : None } id ='run-979eb2bb-fa93-4d18-bda0-288d6d0a11b5-0'
Message History 这是langchain 实现的一个对话历史的方法,不是那么重要,但是其中提到的 通过config结构获取对话历史 ,这种
模式比较重要~
1 config = {"configurable" : {"session_id" : "abc2" }}
在代码中讲解
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 from langchain_community.chat_message_histories import ChatMessageHistoryfrom langchain_core.chat_history import BaseChatMessageHistoryfrom langchain_core.runnables.history import RunnableWithMessageHistorydef get_session_history (session_id: str ) -> BaseChatMessageHistory: if session_id not in store: store[session_id] = ChatMessageHistory() return store[session_id] model = qwen_chat with_message_history = RunnableWithMessageHistory(model, get_session_history) config = {"configurable" : {"session_id" : "abc2" }} response = with_message_history.invoke( [HumanMessage(content="Hi! I'm Bob" )], config=config, ) print (response.content)pass response = with_message_history.invoke( [HumanMessage(content="What's my name?" )], config=config, ) print (response.content)config = {"configurable" : {"session_id" : "abc3" }} response = with_message_history.invoke( [HumanMessage(content="What's my name?" )], config=config, ) print (response.content)config = {"configurable" : {"session_id" : "abc2" }} response = with_message_history.invoke( [HumanMessage(content="What's my name?" )], config=config, ) print (response.content)
Streaming
langchain提供了很多方法, 流式输出是其中的一个例子,还包括 批处理(batch),异步调用 等等。
一个chain 定义之后,我们想用哪种方法调用都可以,只需要换一个方法即可~
1 2 3 4 5 6 for r in with_message_history.stream([HumanMessage(content="hi! tell me a joke" )], config=config, ): print (r.content, end="|" )
输出
1 2 3 4 5 |Sure|,| here|'s a joke for you|, Bob: <--AI 还记得我们 Why don' t scientists trust| atoms?Because they make up everything!||
参考代码 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 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 import osfrom langchain_community.chat_models import QianfanChatEndpointfrom langchain_core.prompts import ChatPromptTemplatefrom langchain_core.runnables import RunnablePassthroughfrom langchain_openai import AzureChatOpenAI, ChatOpenAIfrom langchain_core.messages import HumanMessage, SystemMessagefrom langchain_core.output_parsers import StrOutputParserfrom llm_cfg import AZURE_OPENAI_API_KEY, AZURE_OPENAI_ENDPOINT, DEPLOYMENT_NAME_GPT3P5, MY_QIANFAN_AK, MY_QIANFAN_SK, \ DASHSCOPE_API_KEY if __name__ == '__main__' : api_key = DASHSCOPE_API_KEY qwen_chat = ChatOpenAI( model_name="qwen-max" , openai_api_base="https://dashscope.aliyuncs.com/compatible-mode/v1" , openai_api_key=api_key, ) parser = StrOutputParser() system_template = "你是一个AI助手。" sys_msg = SystemMessage(content=system_template) messages = [] messages.append(sys_msg) messages.append(HumanMessage(content="hi,你好,我是卷儿" )) messages.append(HumanMessage(content="我是谁?" )) pass store = {} from langchain_community.chat_message_histories import ChatMessageHistory from langchain_core.chat_history import BaseChatMessageHistory from langchain_core.runnables.history import RunnableWithMessageHistory def get_session_history (session_id: str ) -> BaseChatMessageHistory: if session_id not in store: store[session_id] = ChatMessageHistory() return store[session_id] model = qwen_chat with_message_history = RunnableWithMessageHistory(model, get_session_history) config = {"configurable" : {"session_id" : "abc2" }} response = with_message_history.invoke( [HumanMessage(content="Hi! I'm Bob" )], config=config, ) print (response.content) pass response = with_message_history.invoke( [HumanMessage(content="What's my name?" )], config=config, ) print (response.content) config = {"configurable" : {"session_id" : "abc3" }} response = with_message_history.invoke( [HumanMessage(content="What's my name?" )], config=config, ) print (response.content) config = {"configurable" : {"session_id" : "abc2" }} response = with_message_history.invoke( [HumanMessage(content="What's my name?" )], config=config, ) print (response.content) for r in with_message_history.stream([HumanMessage(content="hi! tell me a joke" )], config=config, ): print (r.content, end="|" )
Langchain系列[03]聊天机器人 Chatbot
转载前请阅读本站 版权协议 ,文章著作权归 粥余 所有,转载请注明出处。