【AI学习从零至壹】langchain实现特定主题聊天系统
通过 LangChain 框架调用大语言模型(这里配置的是 GLM-4-Flash 模型),支持多轮对话(上下文关联),并将不同会话的历史记录保存到本地 JSON 文件中,通过session_id区分不同用户 / 会话。
langchain实现特定主题聊天系统
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区分不同用户 / 会话。
二、代码结构与关键模块解析
- 导入依赖包
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 文件,支持持久化存储。
- 会话历史记录函数
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 回复添加到历史存储对象中(自动写入文件),供下一轮对话使用。
更多推荐
所有评论(0)