实际上LLM本身没有真正的记忆每次调用都像一次全新的对话。如果只发送当前问题而不提供历史记录模型并不知道之前聊过什么。因此多轮对话的实现方式并不是让模型记住内容而是由应用程序保存历史对话并在每次提问时将历史记录和当前问题一起发送给LLM使模型看起来像拥有持续记忆一样。举一个更完整的例子可以直观说明上下文在对话中的作用。假设我们有一个周末出行规划助手。在第一轮中用户提出一个模糊需求用户帮我规划一下这个周六的出行。 AI好的请问你想去哪里大概几点出发此时LLM已建立基本语境即围绕周六出行规划展开并引导用户补充关键信息。随后用户提供细节用户去植物园上午10点左右。如果这句话单独输入它只是一个零散片段由于缺少背景信息模型难以准确判断其意图可能将其理解为日程记录或简单描述。但当上下文一并输入时语境变得完整模型可以基于前后关联信息正确理解其含义用户帮我规划一下这个周六的出行。 AI好的请问你想去哪里大概几点出发 用户去植物园上午10点左右。可以看到对话之所以能够连贯并不是因为模型具备记忆能力而是因为每一次请求都会将必要的上下文一起传入模型模型只是基于当前输入重新进行理解与生成。记忆在LangChain框架中负责管理对话历史的组件称为Memory其本质是一个专门保存聊天记录的地方用于保存每一轮的用户输入与模型输出。例如可以通过InMemoryChatMessageHistory类实现这一机制。基于这一设计多轮对话的执行流程如下接收用户输入。从Memory中读取历史对话。将历史对话与当前问题组合成完整上下文。调用模型生成回复。将回复返回给用户。将本轮对话写入Memory。因此多轮对话的关键不在于模型真正记住了过去的内容而在于应用程序持续保存并提供历史对话。模型每次回答时实际上都是基于当前问题和历史记录共同进行推理从而保持对话的连贯性。关于长期记忆机制可参考深入解读LangChain 1.0 Agent长期记忆技术要点。示例代码如下from langchain_core.chat_history import InMemoryChatMessageHistory # 创建 Memory history InMemoryChatMessageHistory() # 添加用户消息 history.add_user_message(您好我喜欢每天跑步1小时) # 添加回复消息 history.add_ai_message(我喜欢游泳) # 添加用户消息 history.add_user_message(我每天跑步多久) response chat_model.invoke(history.messages) print(response.content)记忆裁剪在多轮对话里若不加以限制历史记录会持续膨胀。常见做法是按轮数裁剪只保留最近K轮对话更早的内容直接丢弃from langchain_classic.memory import ConversationBufferWindowMemory from langchain_classic.chains import ConversationChain from langchain_community.llms.fake import FakeListLLM llm FakeListLLM( responses[OK] * 10 ) memory ConversationBufferWindowMemory( k3, return_messagesTrue ) conversation ConversationChain( llmllm, memorymemory ) for i in range(5): conversation.predict( inputf第{i1}轮对话 ) print(f\n 第{i1}轮后 ) history memory.load_memory_variables({})[history] for message in history: print(message.content)以上代码本质上实现的是一个固定长度的滑动窗口。运行结果如下第13轮正常累加第4轮第1轮被移除第5轮第2轮被移除3.3 Tools工具LLM擅长理解意图、推理和生成文本但很多实际任务仅依赖生成能力并不足够例如查询天气需要实时数据、查询订单需要访问业务系统而这些能力通常不在模型内部因此需要通过Tool机制将外部能力封装为可调用接口。Tool本质上是对某项功能的结构化描述和执行封装类似函数调用常见场景包括数学计算、时间获取、天气查询、数据库检索以及业务系统接口等。一个Tool通常包含名称、描述、参数定义和执行逻辑其中名称用于标识工具描述帮助模型判断是否调用参数定义约束输入格式执行逻辑负责完成实际操作。在执行过程中系统首先将工具注册给模型或Agent当模型判断需要外部能力时会根据用户输入和工具描述选择合适的工具并生成调用参数待工具执行完成后再将结果返回给模型最终由模型生成回答。对于这一机制的实现原理与实践方式可以参考How to Build a Custom AI Agent with LangChain and Python: A Step by Step Guide。使用tool定义工具在LangChain中可通过tool装饰器将普通Python函数封装为Tool函数名称、文档字符串和参数类型会自动提取为结构化元信息用于描述工具能力。from langchain_core.tools import tool tool def get_weather(city: str) - str: 获取指定城市的天气信息 weather_data { A: 晴天25°C, B: 多云22°C, } return weather_data.get(city, f无法获取{city}天气) # 直接调用工具不经过 LLM result get_weather.invoke({city: A}) print(result) # 晴天25°C # 查看工具元信息 print(f工具名: {get_weather.name}) print(f描述: {get_weather.description}) print(f参数: {get_weather.args})通过tool定义后该函数既可以作为普通Python函数直接调用也可以作为工具被模型或Agent使用两者的区别在于前者不涉及模型参与而后者会进入工具调用流程由模型决定是否调用并生成参数。更多介绍可参考LangChain 实战教程从入门到实战。将工具绑定到模型工具定义完成后可以通过bind_tools方法将多个工具绑定到模型使模型在处理输入时能够感知这些工具。当用户输入到来时模型先判断是否需要调用外部能力如果需要则选择合适工具并生成调用参数。整个过程中模型只负责工具选择与参数生成工具的实际执行由开发者完成并返回结果。from langchain_core.tools import tool tool def get_weather(city: str) - str: 获取城市天气 return f{city}晴天 25°C tool def search_database(query: str) - str: 搜索数据库信息 return f关于{query}的搜索结果示例数据 tools [get_weather, search_database] llm_with_tools chat_model.bind_tools(tools) response llm_with_tools.invoke(上海天气如何) if response.tool_calls: for tc in response.tool_calls: print(f调用工具: {tc[name]}参数: {tc[args]}) for tool in tools: if tool.name tc[name]: print(f结果: {tool.invoke(tc[args])})Agent中使用工具如果希望工具选择、调用与结果整合全部自动化可以将工具交由Agent管理。Agent会根据输入自动选择工具、执行调用并结合结果继续推理直至生成最终答案。from langchain.agents import create_agent from langchain_core.tools import tool tool def multiply(a: int, b: int) - int: Multiply two numbers. return a * b agent create_agent( modelchat_model, tools[multiply] ) response agent.invoke({ messages: [ { role: user, content: 12乘以9等于多少 } ] }) print(response[messages][-1].content)使用StructuredTool除了使用tool快速将函数封装为Tool外还可以通过StructuredTool显式定义工具的名称、描述和参数结构其中tool更适合快速开发StructuredTool更适合需要严格控制元信息的场景但两者本质上都是将外部能力封装为模型可调用的Tool。 StructuredTool 单独演示 from langchain_core.tools import StructuredTool # 使用StructuredTool将函数转换为工具 multiply_tool StructuredTool.from_function( funcmultiply, namemultiply, descriptionMultiply two numbers ) # 调用工具 result multiply_tool.invoke({a: 5, b: 3})