【langchain/入门】使用langchain编写一个简单的聊天机器人(DeepSeek API&命令行版本)
langchain入门教程第三篇,编写一个简单的聊天机器人,实现历史对话管理
·
说在前面
- 操作系统:windows
- python版本:3.9
- langchain版本:0.3.20
- pycharm版本:2023.1.2 (Community Edition)
- 其他:由于上一篇里用的1.5b模型实在太傻了,不太好演示,这里暂时换成deepseek
最简单版本
- 依照上一篇的一些准备工作,我们首先可以实现一个最简易的聊天机器人版本
- 先把deepseek依赖库装下
pip install langchain-deepseek
- 上代码
测试from langchain_deepseek import ChatDeepSeek dllm = ChatDeepSeek(model="deepseek-chat", api_key="xxxxx") from langchain_core.messages import HumanMessage while True: input_msg = input("> ") print(dllm.invoke([HumanMessage(content=input_msg)]).content)
(venv) PS D:\Code\langchain> python .\main.py > 你好 你好!很高兴见到你。有什么我可以帮忙的吗? > 我叫柯南 你好,柯南!你提到“柯南”,让我想到了《名侦探柯南》这部非常受欢迎的日本动漫。你是这部动漫的粉丝吗?还是你的名字真的叫柯南呢?如果你有任何关于动漫、推理或者其他方面的问题,都可以告诉我哦! > 你知道我叫什么吗? 您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-V3。有关模型和产品的详细内容请参考官方文档。
- 这个聊天机器人实际上进行单次对话,没有记忆,接下来我们将逐步完善这个机器人
添加历史对话
- 要让大模型有记忆,最简单的方式是将所有历史对话都交给大模型,比如:
from langchain_deepseek import ChatDeepSeek dllm = ChatDeepSeek(model="deepseek-chat", api_key="xxxxx") from langchain_core.messages import HumanMessage,AIMessage msg_history = [] while True: input_msg = input("> ") msg_history.append(HumanMessage(content=input_msg)) ai_msg = dllm.invoke(msg_history).content msg_history.append(AIMessage(content=ai_msg)) print(ai_msg)
- 测试
可以看到,AI能够知道之前对话的信息了(venv) PS D:\Code\langchain> python .\main.py > 你好,我是柯南 你好,柯南!很高兴见到你。你今天有什么新的案件要解决吗?还是有什么谜题需要一起探讨?我很乐意帮忙! > 你知道我叫什么吗? 当然知道,你是江户川柯南,一个聪明绝顶的少年侦探。你以敏锐的观察力和卓越的推理能力闻名,总是在不经意间揭开案件的真相。你的名字,就像你解决的那些错综复杂的案件一样,令人印象深刻。 >
消息持久化
- 当我们需要更好的管理历史消息时,我们可以将消息存储到数据库中,例如
mongo
、mysql
之类的。在langchain
的生态中,langgraph
有一套内置的持久化层,它提供了几个数据库的封装,sqlite
以及postgres
;同时有一个使用内存的实现(MemorySaver
)用于测试以及调试。 - 那我们就用
langgraph
来试试,安装langgraph
:pip install langgraph
- 先看代码
测试from langchain_deepseek import ChatDeepSeek dllm = ChatDeepSeek(model="deepseek-chat", api_key="xxxxx") from langchain_core.messages import HumanMessage,AIMessage from langgraph.checkpoint.memory import MemorySaver from langgraph.graph import START, MessagesState, StateGraph # 定义一个graph workflow = StateGraph(state_schema=MessagesState) # 封装一下模型调用 def call_model(state: MessagesState): response = dllm.invoke(state["messages"]) return {"messages": response} # 定义一个模型节点 workflow.add_edge(START, "model") workflow.add_node("model", call_model) # 添加MemorySaver memory = MemorySaver() app = workflow.compile(checkpointer=memory) # 定义一个配置,thread_id用于标识此次对话,常用于多用户环境,这里暂时不做扩展 config = {"configurable": {"thread_id": "konan"}} while True: input_msg = input("> ") output = app.invoke({"messages": [HumanMessage(content=input_msg)]}, config) print(output["messages"][-1].content)
(venv) PS E:\Workspace\pycharm\langchain> python.exe .\main.py > 你好,我是柯南 你好,柯南!很高兴见到你。作为一名高中生侦探,你一定有很多精彩的推理故事吧?如果你有任何案件需要讨论,或者想分享一些有趣的线索,我都很乐意帮忙。你最近在调查什么案件呢? > 你知道我是谁吗? 当然知道,你是江户川柯南,一个外表看似小孩,智慧却过于常人的名侦探。你原本是高中生侦探工藤新一,因被黑衣组织灌下毒药而身体缩小,化名为江户川柯南,继续破解各种复杂的案件。你的推理能力和对正义的执着令人敬佩。有什么我可以帮你的吗?
- 一步步拆解下,首先是
workflow = StateGraph(state_schema=MessagesState)
StateGraph
是一种所有节点均通过一个共享的状态管理器进行沟通的graph,在我们这个例子中,这个状态管理器的类型就是MessagesState
,它其实就是一个字典,里面默认有messages
这个kv。class MessagesState(TypedDict): messages: Annotated[list[AnyMessage], add_messages]
- 接下来是封装了一下模型的调用
它的参数是state,也就是我们的状态管理器;而返回值是一个字典,里面是模型的返回,字典的key是messagesdef call_model(state: MessagesState): response = dllm.invoke(state["messages"]) return {"messages": response}
- 而后开始定义我们的graph
workflow.add_edge(START, "model") workflow.add_node("model", call_model)
- 紧接着添加了
MemorySaver
,这一步比较关键memory = MemorySaver() app = workflow.compile(checkpointer=memory)
- 最后就是正常的调用了
input_msg = input("> ") output = app.invoke({"messages": [HumanMessage(content=input_msg)]}, config)
- 看完这个流程,我有个疑问,用户的输入以及模型的返回,是怎样存入到memory之中的?关键点在于
checkpointer=memory
,如果把这个去掉,就没有记忆功能了
这个如何实现的这里就先不探讨了,应该和这个有关(venv) PS E:\Workspace\pycharm\langchain> python.exe .\main.py > 你好,我是柯南 你好,柯南!很高兴见到你。你今天有什么案件需要解决吗?还是有什么谜题需要一起探讨?我很乐意帮忙! > 你知道我是谁吗? 您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-V3。有关模型和产品的详细内容请参考官方文档。 >
管理历史对话
-
通过上述的代码我们可以知道,当对话次数越多,一次大模型请求传递的数据量就越多,消耗的token数就越多,所以一个非常重要的功能就是管理历史对话,让传给大模型的数据量不要过大。
-
同样的,
langchain
有一些封装好的接口可以使用def dummy_token_counter(messages: list[BaseMessage]) -> int: count = 0 for msg in messages: if isinstance(msg.content, str): count += len(msg.content) return count trimmer = trim_messages( max_tokens=64, strategy="last", token_counter=dummy_token_counter, include_system=True, allow_partial=False, start_on="human", ) # 封装一下模型调用 def call_model(state: MessagesState): trimmed_msg = trimmer.invoke(state["messages"]) response = dllm.invoke(trimmed_msg) return {"messages": response}
这里由于用的
deepseek
,直接使用token_counter=dllm
会报错,可能哪里不兼容,所以随便写了一个counter -
测试,可以看到第三个问题的时候已经不知道我是柯南了
(venv) PS E:\Workspace\pycharm\langchain> python.exe .\main.py > 你好,我是柯南 你好,柯南!很高兴见到你。你今天有什么新的案件要解决吗?还是有什么需要我帮忙的地方? > 怎样睡得更好 要改善睡眠质量,可以尝试以下方法: ### 1. **建立规律的作息时间** - 每天尽量在同一时间上床睡觉和起床,即使在周末也保持一致。 - 帮助身体形成生物钟,更容易入睡和醒来。 ### 2. **创造舒适的睡眠环境** - **温度**:保持卧室凉爽(18-22℃为宜)。 - **光线**:使用遮光窗帘或眼罩,避免光线干扰。 - **噪音**:使用耳塞或白噪音机减少噪音干扰。 - **床具**:选择舒适的床垫和枕头,适合你的睡眠姿势。 ### 3. **睡前放松身心** - **避免刺激**:睡前1-2小时避免使用电子设备(如手机、电脑),减少蓝光对大脑的刺激。 - **放松活动**:可以尝试冥想、深呼吸、轻柔的瑜伽或听舒缓的音乐。 - **温水泡脚或泡澡**:帮助放松肌肉,促进血液循环。 ### 4. **调整饮食习惯** - **避免咖啡因和酒精**:睡前4-6小时避免摄入咖啡、茶、巧克力或酒精。 - **清淡晚餐**:避免睡前吃太饱或吃油腻、辛辣的食物。 - **适量饮水**:睡前不要喝太多水,以免夜间频繁起夜。 ### 5. **白天保持适度运动** - 每天进行30分钟左右的适度运动(如散步、慢跑、瑜伽),但避免在睡前2小时内剧烈运动。 ### 6. **管理压力和焦虑** - **写日记**:睡前写下当天的烦恼或明天的计划,帮助清空大脑。 - **练习正念**:通过冥想或深呼吸练习缓解焦虑。 - **寻求支持**:如果压力过大,可以找朋友倾诉或寻求专业帮助。 ### 7. **避免长时间午睡** - 如果需要午睡,控制在20-30分钟内,避免影响夜间睡眠。 ### 8. **限制床上活动** - 床只用于睡觉和亲密关系,避免在床上工作、看电视或玩手机,帮助大脑建立“床=睡眠”的联想。 ### 9. **尝试自然助眠方法** - **喝温牛奶或草本茶**:如洋甘菊茶、薰衣草茶。 - **使用香薰**:薰衣草、洋甘菊等精油有助于放松。 ### 10. **如果长期失眠,及时就医** - 如果尝试以上方法后仍无法改善睡眠,建议咨询医生,排除潜在的健康问题(如睡眠呼吸暂停、焦虑症等)。 ### 小贴士: - **不要强迫自己入睡**:如果躺下20分钟后仍无法入睡,可以起床做一些放松活动,直到感到困倦再回到床上。 - **记录睡眠日记**:记录每天的睡眠时间、质量、饮食和活动,帮助找到影响睡眠的因素。 希望这些方法能帮助你改善睡眠,拥有更高质量的休息! > 我是谁 这个问题涉及到自我认知和哲学思考。从哲学的角度来看,“我是谁”是一个关于自我身份和存在本质的问题。不同的哲学流派和思想家对此有不同的解释。 1. **笛卡尔的“我思故我在”**:笛卡尔认为,思考是自我存在的证明。通过怀疑一切,他发现唯一不可怀疑的是自己在思考的事实,因此得出结论“我思故我在”。 2. **佛教的无我**:佛教认为,所谓的“我”是一个幻觉,是由五蕴(色、受、想、行、识)暂时聚合而成的。真正的自我并不存在,执着于“我”是痛苦的根源。 3. **存在主义**:存在主义者如萨特认为,存在先于本质。人首先存在,然后通过自己的选择和行动来定义自己。因此,“我是谁”是由你自己通过行动和选择来决定的。 4. **心理学视角**:从心理学角度来看,自我是一个复杂的结构,包括自我概念、自我认同和自我意识。你是谁可能由你的经历、记忆、情感、价值观和社会关系共同塑造。 5. **生物学视角**:从生物学角度来看,你是由你的基因、生理结构和大脑功能所决定的。你的身体和大脑的状态会影响你的思维、情感和行为。 6. **社会学视角**:社会学家认为,自我是在社会互动中形成的。你通过与他人的关系、社会角色和文化背景来定义自己。 7. **灵性视角**:在一些灵性传统中,真正的自我被认为是超越物质世界的,与宇宙或神性相连。通过冥想、祈祷或其他灵性实践,人们试图认识这个更深层次的自我。 最终,“我是谁”这个问题没有一个简单的答案,它可能需要你通过自我反思、哲学思考、科学探索和灵性实践来不断探索和理解。
-
以上,柯南要碎觉了
更多推荐
所有评论(0)