Langchain

LangChain 是⼀个开发⼤语⾔模型应⽤的框架。它能够为应⽤程序带来:

  • 内容组件:建⽴原始内容到语言模型建的关联(通过结构化的提示和少量的举例就可以得到满意的回复)
  • 推理:通过语⾔模型进⾏推理(给出基于当前问题的解答和⾏动策略)

LangChain框架的组成

  • LangChain Libraries:基于Python和JavaScript的库。包含各种组件(component)和接⼝(interface)集成;由组件构建的链(chain)和代理(agent)的基本运⾏环境;链(chain)和代理(agent)的现有功能实现。
  • LangChain Templates:⼀组易于部署的参考架构,适⽤于各种任务。
  • LangServer:将LangChain链部署为REST API的库。
  • LangSmith:⼀个开发平台,允许我们调试、测试、评估和监控构建在任何LLM框架上的链,与LangChain⽆缝集成。
    在这里插入图片描述
    这些产品能够为我们简化应⽤程序的开发周期:
    开发:适⽤LangChain/LangChain.js编写⾃定义的应⽤程序。使⽤模版作为参考,可以⽴即投⼊到应⽤领域。
    ⽣产:适⽤LangSmith检查、测试和监控⾃定义的链,⼀遍不断优化和放⼼进⾏部署。
    部署:适⽤LangServe可以将任意的链转换为API

langchain搭建聊天系统

一、核心功能概述

通过 LangChain 框架调用大语言模型(这里配置的是 GLM-4-Flash 模型),支持多轮对话(上下文关联),并将不同会话的历史记录保存到本地 JSON 文件中,通过session_id区分不同用户 / 会话。

二、代码结构与关键模块解析

  1. 导入依赖包
from dotenv import find_dotenv, load_dotenv  # 加载环境变量
import os  # 操作系统交互(读取环境变量)
from langchain_openai import ChatOpenAI  # 封装的大语言模型调用接口
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage  # 对话角色定义
from langchain_core.output_parsers import StrOutputParser  # 输出结果解析器
from langchain_community.chat_message_histories import FileChatMessageHistory  # 本地文件存储对话历史
from langchain_core.runnables.history import RunnableWithMessageHistory  # 为链注入对话历史
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder  # 对话模板与占位符
  • 环境变量相关:dotenv用于加载.env文件中的 API 密钥、基础 URL 等敏感信息,避免硬编码。
    LangChain 核心组件:
  • ChatOpenAI:兼容 OpenAI API 格式的模型调用类(此处用于调用 GLM-4 模型)。
  • MessagesPlaceholder:对话模板中用于动态插入历史消息的占位符。
  • RunnableWithMessageHistory:将对话历史注入到处理链中,实现上下文关联。
  • FileChatMessageHistory:将对话历史保存到本地 JSON 文件,支持持久化存储。
  1. 会话历史记录函数
def get_session_history(session_id):
    # 为每个session_id创建独立的历史文件:history_{session_id}.json
    return FileChatMessageHistory(f"history_{session_id}.json")

作用:根据session_id生成对应的对话历史存储对象,每个会话的历史会单独保存为一个 JSON 文件(如history_user1.json)。
优势:不同用户 / 会话的历史相互隔离,方便后续加载和继续对话。
3. 主程序逻辑

if __name__ == '__main__':
    load_dotenv(find_dotenv())
    #初始化 Openai
    model = ChatOpenAI(
        model = "glm-4-flash-250414",
        base_url=os.environ['base_url'],
        api_key = os.environ['api_key'],
        temperature=0.7
    )
    #带有占位符的prompt template
    prompt = ChatPromptTemplate(
        [
            ("system","你是一个得力的助手,你可以使用{lang}回答用户的问题"),
            MessagesPlaceholder(variable_name="messages")
        ]
    )
    parser = StrOutputParser()
    #chain构建
    chain = prompt | model | parser
    #在chain中注入聊天历史消息
    with_msg_hist = RunnableWithMessageHistory(
        chain,
        get_session_history = get_session_history,
        input_messages_key="message"
    )
    #动态输入session_id
    session_id = input('请输入session_id(用于区分不同会话):').strip()
    while True:
        user_input = input('用户输入的Message(输入quit推出):')
        if user_input.lower()=='quit':
            break
        #调用注入聊天历史的对象
        response = with_msg_hist(
            {
                "messages":[HumanMessage(content = user_input)],
                "lang":"汉语"
            },
            config = {'configurable':{'session_id':session_id}}
        )
        print('AI Message:',response)

实现多轮对话的核心

在 LangChain 框架中,MessagesPlaceholder(消息占位符)是一个核心组件,专门用于在对话模板(ChatPromptTemplate)中动态插入历史对话消息,是实现多轮对话上下文关联的关键工具。

一、MessagesPlaceholder 的核心作用

MessagesPlaceholder的本质是一个 “占位标记”,用于在ChatPromptTemplate中预留位置,后续会自动填充历史对话消息(包括用户消息、AI 回复、系统消息等)。
它解决的核心问题是:在多轮对话中,如何将 “历史消息” 动态传入模型,让模型能够基于上下文生成连贯的回复,而不是每次都只处理当前单条消息。

prompt = ChatPromptTemplate(
    [
        ("system", "你是一个得力的助手,你可以使用{lang}回答用户的问题"),  # 系统提示
        MessagesPlaceholder(variable_name="messages")  # 消息占位符
    ]
)

  • MessagesPlaceholder(variable_name=“messages”)表示:在模板中预留一个名为"messages"的位置,后续会将名为"messages"的变量值(即历史对话消息列表)填充到这里。
  • variable_name是MessagesPlaceholder的必填参数,用于指定:
    占位符对应的变量名:后续调用链时,需要传入同名的参数(如上述代码中的"messages"),该参数的值会被填充到占位符位置。
    与历史消息的关联:在结合RunnableWithMessageHistory(处理对话历史)时,variable_name需要与历史消息存储的键名对应,确保历史消息能被正确提取并传入模板。
    MessagesPlaceholder的价值在于
    动态性:无需手动拼接历史消息,框架会自动根据会话 ID 加载并填充,简化代码。
    结构化:历史消息以HumanMessage、AIMessage等结构化对象存储,模型能清晰区分消息角色(用户 / AI / 系统),提升理解准确性。
    灵活性:可根据需求调整占位符位置(例如在系统提示前 / 后插入历史消息),适配不同对话场景。

二、RunnableWithMessageHistory 的核心作用

RunnableWithMessageHistory 是一个 “包装器”(wrapper),它可以将普通的处理链(chain)与对话历史管理功能结合,让链在每次调用时自动:
1.加载当前会话的历史消息(基于 session_id);
2.将新消息与历史消息合并后传入模型;
3.保存本轮对话的新消息(用户输入 + AI 回复)到历史记录中。

with_msg_hist = RunnableWithMessageHistory(
    chain,  # 基础处理链
    get_session_history=get_session_history,  # 用于获取会话历史的函数
    input_messages_key="messages"  # 输入消息在参数中的键名
)
  • input_messages_key=“messages”:指定在调用链时,新输入的用户消息在参数字典中的键名。
  • 作用:RunnableWithMessageHistory 需要知道 “哪部分参数是新的用户消息”,以便将其与历史消息合并,并在对话结束后将新消息存入历史记录。
    with_msg_hist 的工作流程
  • 获取会话历史:根据传入的 session_id(通过 config 参数),调用 get_session_history(session_id) 获取该会话的历史存储对象
  • 加载历史消息:从存储对象中读取该会话的所有历史消息(例如之前的 HumanMessage 和 AIMessage)。
  • 合并消息:将新输入的用户消息(通过 input_messages_key 指定的键获取,如 “message”)与历史消息合并,形成完整的消息列表。
  • 调用基础链:将合并后的消息列表传入 chain(即 prompt | model | parser),生成 AI 回复。
  • 保存新消息到历史:将本轮的用户消息和 AI 回复添加到历史存储对象中(自动写入文件),供下一轮对话使用。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐