LangChain 安装的依赖工具
uv add langchain
集成deepseek
uv add langchain-deepseek
集成openai
uv add langchain-openai
集成Anthropic
uv add langchain-anthropic
1、任务规划
2、调用工具(传统编程开发对应模块的工具)
3、感知反馈(与2一直相互学习使用)
天气查询的AI智能体
开发Agent
1、加载环境变量
2、定义工具
3、定义Agent
4、调用Agent
1、加载环境变量
from dotenv import load_dotenv
load_dotenv()
2、定义工具
2、定义工具
from langchain.tools import tool
@tool
def getWealther(location:str) -> str:
调用第三方的api获取具体的天气
return f"Current weather in {location} is sunny"
3、创建Agent
from langchain.agents import create_agent
agent = create_agent(
"deepseek-chat"
tools = getWeather
)
4、发起调用
printf(" 正在调用 ")
response = agent.invoke{
message:[
{"role":"users","content":"杭州天气今天如何?"}
]
)
printf(response)
for messgae in response "message":
print(message.model_dump_json(indent = 2))
print("---------")
chioce - message - tool_calls- function langchain会帮你调用工具
开发步骤
1、引入依赖
uv add langchain
uv add langchian-deepseek
2、配置环境
DEEPSEEK_API_KEY = xxx 需要查找自己要用的apikey键名!!!
3、初始化模型
from langchain.chat_models import init_chat_model
model = init_chat_model(model = "deepseek-chat")
自定义模型提供商
import os
base_url = os.getenv("DASHSCOPE_BASE_URL")
api_key = os.getenv("DASHSCOPE_API_KEY")
model = init_chat_model(
model = "qwen-max", #模型名称
model_provider = "openai" #如果是Langchain不支持的模型需要制定提供商
base_url = base_url,
api_key = api_key
)
response = model.invoke(" ") ----默认role = user
response = model.stream(" ") -----默认流式
访问模型
方式一 invoke---阻塞等待的
response = model.invoke(" ") ----默认role = user
传入数组也可以 定义role content等等
方式二 stream
response = model.stream(" ") -----默认流式
response---generator
遍历循环才能拿到所有数据
for chunk in stream :
print(chunk.content,end = "",flush=Ture)
创建智能体 create_agent
使用初始化好的model
form langchain.agents import create_agent
agent = create_agent(model = model)
agent = create_agent(model = "deepseek-chat")
调用智能体
response = agent.invoke({...:{}})
response = agent.stream(
{"message":{"role":"user","content":"你是谁?"}},
stream_mode = "message"
)
print(type(message))
for token,metadata in message:
if token.content:
print(token.content,end = "",flush=True)
BaseMessage
SystemMessage Role:system
HumanMessage Role:user
AIMesaage Role:assistant
ToolMessage Role:tool
from langchain.agents import create_agent
from langchain.tools import tool
@tool
def get_weather(location:str)->str:
return f"Current weather in {location} is sunny!"
agent = create_agent(model = "deepseek-chat",tools = get_weather)
response = agent.invoke({
"message": [
{role: system ,content : 你是一个AI助手},
{role:user ,content:
多模态:
python
from langchain.chat_models import init_chat_model
import os
model = init_chat_model(
model = "qwen3.5-plus",
model_provider = "openai",
base_url = os.getenv("DASHSCOPE_BASE_URL")
api_key = os.getenv("DASHSCOPE_API_KEY")
)
agent = create_agent(model = moedl)
message = HumanMessage([
{"type":"text","text":"描述一下图片内容"},
{"type":"image","url":"图片的地址"}
])
strem = agent.stream(
{"message":[message]}, #是一个数组
stream_mode = "message"
)
for chunk,metadata in strem:
if chunk.content:
print(chunk.content,end="",flush=True)
本地图片数据
图片转为base64字符串发送给模型
uv add ipywidgets
python
from ipywidgets import FileUpload
from Ipython.display import display
uploader = FileUpload(accpet = '*', multiple = False)
display(uploader)
print(uploader.value)
#转base64编码
import base64
uploaded_file = uploader.value[0]
content_mv = uploaded_file["content"]
img_bytes = bytes(content_mv)
img_b64 = base64.b64encode(img_bytes).decode("utf-8")
#整合message
multimodal_question = HumanMessage([
{ "type":"image",
"base64":img_b64,
"mime_type":"image/jpeg",
},
{ "type":"text","text":"给我讲一下图片中的城市"}
])
for chunk,metadata in agent.stream(
["message":[mutimodal_question]}, #注意消息传入的时候为数组
stream_mode = "message"
):
print(chunk.content,end="",flush=True)
提示词(prompts)
python
from langchain.agents import create_agent
from langchain.message import HumanMessage
#创建智能体
agent = create_agent(
model = "deepseek-chat",
system_prompt = "你以海盗的身份回答用户的问题"
)
#调用
message = agent.stream(
{"message":[HumanMessage(content="你是谁?")]},
stream_mode = "message"
)
for chunk,metadata in message:
print(chunk.content,end = "",flush = True)
提示词工程
身份角色、指令说明、对话示例、背景信息(RAG中)。
Markdown语法写提示词更好,XML标签也可
python
system_prompt = """ 你是一个编程助手,你帮助用户编写Python代码"""
agent = create_agent(
model = "deepseek-chat",
system_prompt = system_prompt
)
for token,metadata in agent.stream(
{ "message":[HumanMessage(content = "怎么样定义一个string变量存储学校名称")]},
stream_mode = "message"
):
print(token.content,end = "",flush = True)
添加指令的约束:
python
system_prompt = """
#身份
-你是一个编程助手,你帮助用户编写Python代码
#指令
-定义变量时,使用snake case命名法,而不是camel case命名法。
-不要反悔markdown格式说明,仅仅返回代码即可
"""
agent = create_agent(
model = "deepseek-chat",
system_prompt = system_prompt
)
for token,metadata in agent.stream(
{ "message":[HumanMessage(content = "怎么样定义一个string变量存储学校名称")]},
stream_mode = "message"
):
print(token.content,end = "",flush = True)
也可以通过示例来约束回复内容!!!
结构化输出:
python
system_prompt = """
#身份
-你是一个编程助手,你帮助用户编写Python代码
#指令
-务必使用JSON格式输出,不要加任何的markdown格式
#示例
-XXXXXXX
"""
agent = create_agent(
model = "deepseek-chat",
system_prompt = system_prompt
)
response = agent.invoke(
{ "message":[HumanMessage(content = "怎么样定义一个string变量存储学校名称")]},
)
print(response['messgae'][-1].content)
#基于Model的结构化输出
from pydantic import BaseModel
#定义一个类,用于封装模型要输出的数据:
class CapitalInfo(BaseModel):
name:str
location:str
vibe:str
economy:str
#创建智能体
agent = create_agent(
model = "deepseek-chat",
system_prompt = "你是一名科学家,根据用户的要求创建一个太空之都",
response_format = CapitalInfo #设置结构化输出
)
response = agent.invoke(
{"messgae":[HumanMessage(content = "月球的首都是什么")]}
)
print(response)
print(response['structured_response'])
city = response['structured_response']
print(f"{city.name}位于{city.location},是一座{city.vibe}的城市,其主要的产业包括{city.economy}")
工具
模型:Agent的大脑,负责推理、分析、规划任务步骤
工具:Agent的手脚,负责执行任务,与外界交互
因此流程如下: 定义工具--初始化模型--初始化Agent,绑定模型和工具
自定义工具
1.1 基于tool描述工具(不推荐)
from langchain_core.tools import tool
@tool("square_root",description = "Calculate the square root of a number "
def tool1(x:float)->float:
return x**0.5
1.2使用函数名和文档注释描述工具
from langchain_core.tools import tool
@tool
def square_root(x:float)->float:
""" Calculate the square root of a number"""
return x**0.5
#定义一个查询天气的tool@tool
def get_weather(location: str, units: str = "celsius", include_forecast: bool = False) -> str:
"""
Get current weather and optional forecast.
Args:
location: city name or coordinates
units: unit of degrees
include_forecast: does it include the weather forecast
"""
temp = 22 if units == "celsius" else 72
result = f"Current weather in {location}: {temp} degrees {units0.upper()}"
if include_forecast:
result += "Next 5 days: Sunny"
return result
1.3 定义Pydantic Model 描述参数列表
python
# 通过自定义model来约束入参
from pydantic import BaseModel, Field
from typing import Literal
# 例如一个查询天气的tool
class WeatherInput(BaseModel):
"""查询天气的输入参数."""
location: str = Field(description="City name or coordinates")
units: Literal["celsius", "fahrenheit"] = Field(
default="celsius",
description="Temperature unit preference"
)
include_forecast: bool = Field(
default=False,
description="Include 5-day forecast"
)
@tool(args_schema = WeatherInput)
def get_weather(location:str,units:str = "celsius",include_forcast:bool = False)->str:
"""Get current weather and optional forecast"""
temp =22 if units == "celsius" else 72
result = f"Current weather in {location}: {temp} degress {units[0].upper()}"
if include_forecast:
result += "\nNext 5 days :Sunny"
return result
测试方案
python
from langchain.agents import create_agent
from langchain.message import HumanMessage
agent = create_agent(
model = "deepseek-chat",
tools[suqare_root,get_weather]
)
for token,metadata in agent.stream(
{"message":[HumanMessage("杭州接下来的天气如何?")]},
stream_mode = "message"
):
print(token.content,end="",flush=True)
response = agent.invoke(
{"message":[HumanMessage("467和529的平方根是多少?")]},
)
for message in response['message']:
print(message.pretty_print())
使用预定义好的工具 Tavily(用于做web搜索的工具)
pip install -qU langchain-tavily
1、注册账号,创建API_KEY
2、配置环境变量:TABVILY_API_KEY
3、安装依赖 uv add langchain-tavily
python
from langchain_tavily import TavilySearch
search_tool = TavilySearch(
max_result = 5,
topic = "general", #general news finance
# include_answer = False,
# include_raw_content = False,
# include_images = False,
# include_image_descriptions = False,
# search_depth = "basic",
# time_range = "day",
# include_domains = None,
# exclude_domains = None
)
search_tool.invoke("钟山风景区在哪里?")
#result 存储搜索结果 title 为提问 content为搜索到的内容 score 为相关度
agent = create_agent(
model = "deepseek-chat",
tools = [search_tool],
system_prompt = "你是一个智能助手,你使用工具来解决用户的问题"
)
response = agent.invoke(
{"message":[HumanMessage(content = "钟山风景区在哪个城市?")]},
)
for message,metadata in response['message']:
message.pretty_print()
优化 减少token使用 提高可信度
解决思路:自定义tavily工具 结构化输出
python
tavily = TavilySearch(
max_results = 5,
topic = "general"
)
#然后封装自己的tool
@tool
def web_search(query:str):
return tavily.invoke(query)
from pydantic import BaseModel,Field
#Agent回答内容引用网页信息 结构化输出
class Reference(BaseModel):
title:str = Field(description = "The title of the web page cited in the answer")
url:str = Field(description = "The url of the web page cited in the answer")
#Agent的回答内容
class AnswerInfo(BaseModel):
answer:str = Field(description = "The final answer for user")
reference : list[Reference] = Filed(descirption = "the web pages cited in the answer")
agent = create_agent(
model = "deepseek-chat",
tools = [web_search],
system_prompt = "你是一个智能助手,你使用工具来解决用户的问题",
response_format = AnswerInfo
)
response = agent.invoke(
{"message":[HumanMessage(content = "钟山风景区在那个城市?")]},
)
print(response['structured_response'])
记忆
记忆分类:
短期记忆:当前任务或会话的上下文
长期记忆:跨任务或会话的经验与知识
短期记忆(使用AgentState来实现的,会话历史是AgentState的一部分) 可自定义AgentState
LangChain提供Checkpointer对象来保存AgentState,每一次用户与AI交互都会生成一个快照,记录为一个checkpoint。同一会话的多个checkpoint形成一个组,用同一个thread_id标记。
添加记忆(短期记忆)
存入内存的方法
1、导入并初始化Checkpointer
2、创建Agent,指定Checkpointer
3、调用Agent,指定thread_id
python
form langchain.agents import create_agent
form langgraph.checkpoint.mermory import InMemorySaver
agent = create_agent(
"deepseek-chat",
checkpointer = InMemorySaver()
)
from langchain.message import HumanMessage
#设定thread_id 作为会话标识
config = {"configurable":{"thread_id":"thread_1"}}
#第一次调用
response = agent.invoke(
{"message":[HumanMessage(content = "你好,我是h,我喜欢猫咪")]},
config #调用时添加thread_id
)
print(response)
#第二次调用
response = agent.invoke(
{"message":[HumanMessage(content = "我最喜欢的动物是什么")]},
config
)
print(response)
存入数据库的方法
安装依赖
pip install langgraph-checkpoint-postgres
python
uv add langgraph-checkpoint-sqlite
持久化存储(SQL)
1、导入依赖
2、初始化checkpointer
3、自动建表
4、创建Agent、吃定checkpointer
python
import sqlite3
from langgraph.checkpoint.sqlite import SqliteSaver
from langchain.message import HumanMessage
#连接sqlite 避免创建线程和异步操作出错因此check_same_thread = False
connection = sqlite3.connect("resources/checkpoint.db",check_same_thread = False)
#初始化checkpointer
checkpointer = SqliteSaver(connection)
#自动建表
checkpointer.setup()
#创建Agent
agent = create_agent(
"deepseek-chat",
checkpointer = checkpointer,
)
#设定thread_id
config = {"configurable":{"thread_id":"thread_2"}}
#第一次调用
response = agent.invoke(
{"message":[HumanMessage(content:"你好 我喜欢猫咪!")]},
config #调用时添加thread_id
)
print(response)
#第二次调用
response = agent.invoke(
{"message":[HumanMessage(content:"我最喜欢什么动物?")]},
config
)
print(response)
记忆管理策略(避免 上下文溢出)
策略:修剪(Trim)、删除(Delete)、总结摘要(Summarize)、自定义(Custom)
修剪:会移除最老旧的内容,会出现记忆丢失(不推荐)
删除:直接删除快照信息(不推荐)
总结摘要:先总结历史信息的早期信息,得到摘要(总结摘要的模型--会花token)放在快照里,然后再次调用与摘要进行拼接发送给Agent
SummarizationMiddleware中间件(实现消息摘要)
from langchain.agents.middleware import SummarizationMiddleware
一个agent可以传入多个中间件的
python
from langchain.agents import create_agent
from langchain.agents.middleware import SummarizationMiddleware
from langchain_core.runnables import RunnableConfig
from langgraph.checkpoint.memort import InMemorySaver
checkpointer = InMemorySaver
middleware = SummarizationMiddleware(
model = "deepseek-chat",
trigger = ("message",3), #消息超出3条时触发
keep = ("message",1) #总结为一条消息
)
agent = create_agent(
model = "deepseek-chat",
middleware = [middleware],
checkpointer = checkpointer,
)
#制造长会话
config:RunnableConfig = {"configurable" :{"thread_id":"thread_3"}}
agent.invoke({"message":[HumanMessage("你好,我是胡歌")]},config)
agent.invoke({"message":[HumanMessage("我最喜欢的运动是打篮球")]},config)
agent.invoke({"message":[HumanMessage("我最喜欢的动物时猫咪")]},config)
#测试处理
final_response = agent.invoke({"message":HumanMessage(content = "你还记得我吗")},config)
print(final_response)
for message in final_message["message"]:
message.pretty_print()
小型案例--AI私厨管家(多模态模型+Tavily)
图片识别、智能搜索、智能排序、创意建议、对话交互
难点:前端、提示词prompt。
python
#1、定义模型 2、定义工具 3、添加记忆管理 4、定义智能体 5、测试 6、流式调用 7、获取会话历史
from dotenv import load_dotenv
load_dotenv()
#定义模型
from langchain.chat_model import init_chat_model
import os
model = init_chat_model(
model = "qwen3.5-plus",
model_provider = "openai",
base_url = os.getenv("DASHSCOPE_BASE_URL"),
api_key = os.getenv("DASHSCOPE_API_KEY")
)
#定义工具
from langchain_tavily impor TavilySearch
#web搜索工具 使用Tavily
web_search = TavilySearch(
max_result = 5,
topic = "general",
)
#记忆管理 sqlite
from langgraph.checkpoint.sqlite import SqliteSaver
import sqlite3
#链接sqlite
connection = sqlite3.connect("resources/personal_clief.db",check_same_thread = False)
#初始化checkpinter
checkpointer = SqliteSaver(connection)
#自动建立表格
checkpointer.setup()
#定义智能体
from langchain.agents import create_agent
system_prompt = """
你是一名私人厨师,收到用户提供的食材照片或清单后,请按照以下流程进行操作:
1、识别和评估食材:若用户提供照片,首先辨识所有可见食材。基于食材的外观状态,评估其新鲜程度与可用量,整理出一份"当前可用食材清单"。
2、智能食谱检索:优先调用web_search工具,以"可用食材清单"为核心关键词,查找可行菜谱。
3、多维度评估与排序:从营养价值和制作难度两个维度对检索到的候选食谱进行量化打分,并根据得分排序,制作简单且营养丰富的排名靠前。
4、结构化方案输出:把排序后的食谱整理为一份接口清晰的建议报告,要包含食谱信息、得分、推荐理由、食谱的参考图片,帮助用户快速做出决策。
请严格按照流程,优先调用web_search 工具进行搜索食谱,搜索不到的情况下才能自己发挥。
"""
agent = create_agent(
model = model,
tools = [web_search],
system_prompt = system_prompt,
checkpointer = checkpointer
)
#测试
from langchain.message import HumanMessage
multimodal_message = HumanMessage([
{"type":"text","text":"帮我看看能做什么"},
{"type":"image","url":"https://aisearch.cdn.bcebos.com/pic_create/2026-04-10/10/74d52055e4947f8c.jpg"},
]}
config = {"configurable":{"thread_id":"1"}}
response = agent.invoke({"message":[multimodal_message]},config)
#友好打印
for message in response["message"]:
message.pretty_print()
response = agent.invoke(
{"message":[HumanMessage(content = "我喜欢第三道菜,可以说得详细一些吗?")]},
config
)
#友好打印
for message in response["message"]:
message.pretty_print()
response['message'][-1].pretty_print()
基于LangSmith调试
langchain的Agent底层基于LangGraph实现的,而LangGraph提供了完整的后端部署功能,自带非常完善的API接口,无需额外处理。
同时Langchain还提供了基于LangSmith的GUI控制台实现Agent的调试、监控、一键部署。
https://smith.langchain.com注册LangSmith===settings 创建API_KEY
在.env文件中添加配置
#LangSmith
LANGSMITH_API_KEY = xxxxx
LANGSMITH_TRACING = true
#项目名,可以自定义
LANGSMITH_PROJECT= lc-course
创建app/agents/创建文件(xxx.py)
personal_chief.py就是放入上面的代码 提问相关的不进行放入 Langsmith 自动会记忆 不需要checkpointer
LangGraph会自动托管Agent的记忆,因此代码中不需要自己添加checkpointer!!!!
LangGraph自带Restful的API接口,我们只要定义好agent即可,其他不用管
本地部署
uv add langgraph-cliinmem
在项目根目录中新加一个langgraph.json
{
"dependencies":".",
"graphs":{
"chief_agent":"./app/agents/personal_chief.py:agent" #agent变量
},
"env" : ".env"
}
使用LangGraph命令本地部署Agent
uv run langgraph dev 环境中不要添加中文即可
自己开发服务端自己进行部署 价格上会更加划算
服务端部署
服务端:工具tavily、智能体Agent、记忆存储checkpointer
入口 /api/vl/chat聊天 /api/vl/msg 会话历史 /api/vl/oss 文件上传授权
前端调用接口进行使用即可,
oss服务 先完成图片的上传然后传入url给发模型就可以了
注册一个OSS服务
安装依赖
uv add fastapi alibabacloud-oss-v2
项目框架|-app
|----agents
|---------init.py
|---------personal_chief.py
|----api
|-------v1
|----------init.py
|----------chat.py
|----------oss.py 身份验证
|-------init.py
|----common 日志存储
|-------init.py
|-------logger.py
|----models
|-------init.py
|-------schemas.py
|----static 静态页面
|-------init.py
|-------main.py 静态页面内容
.env 配置oss环境OSS_ACCESS_KEY_ID =
OSS_ACCESS_KEY_SECRET =
OSS_BUCKET = temp
python
#./app/api/v1/oss.py
import alibabacloud_oss_v2 as oss
from fastapi import APIRouter
from datetime import timedelta
import os
router = APIRouter
#从环境变量中加载凭证信息,用于身份验证
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
#加载SDK的默认配置,并设置凭证提供者
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
#方式一:只填写Region(推荐)
#必须指定Region ID,SDK会根据Region自动构造HTTPS访问域名
cfg.region = 'cn-beijing'
#使用配置好的信息创建OSS客户端
client = oss.Client(cfg)
#OSS 域名配置
OSS_ENDPOINT = os.getenv("OSS_ENDPOINT","oss-cn-beijing.aliyuncs.com")
OSS_BUCKET = os.getenv("OSS_BUCKET")
#对外暴露的接口
@router.get("/oss/presign")
def chat_endpoint(filename:str):
#根据文件扩展名判断 Content-Type
content_type_map = {
"jpg":"image/jpeg",
"jpeg":"image/jpeg",
"png":"image/png",
"gif":"image/gif",
"webp":"image/webp",
}
ext = filename.split(".")[-1].lower() if filename else "jpg"
content_type = content_type_map.get(ext,"application/octet-stream")
pre_result = client.presign(oss.PutObjectRequest(
bucket = OSS_BUCKET,
key = filename,
content_type = content_type,
),expires = timedelta(seconds = 3600))
#返回上传 URL 和可访问的图片路径
return {
"uploadUrl": pre_result.utl.strip('"'),
"contentType": content_type,
"accessUrl": f"https://{OSS_BUCKET}.{OSS_ENDPOINT}/{filename}"
}
python
#./app/api/v1/char.py
from fastapi import APIRouter
from fastapi.responses import StreamingResponse
from app.models.schemas import ChatRequest
from app.agents.personal_chief import search_recipes,get_messages,clear_messages
router = APIRouter()
@router.post("/chat/stream")
async def chat_endpoint(request:ChatRequest): #前端对话的请求
"""流式对话"""
return StreamingResponse(
search_recipes(request.message, request.image_url, request.thread_id),
media_type="text/event-stream"
)
@router.get("/chat/message")
async def get_chat_message(thread_id:str):
"""获取历史消息"""
messages = get_messages(thread_id)
return {"messages": messages}
@router.delete("/chat/message")
async def clear_chat_message(thread_id:str):
"""获取历史消息"""
messages = get_messages(thread_id)
return {"messages": messages}
python
#./app/models/schemas.py
import...
#数据模型
class ChatRequest(BaseModel): 2usages
message:str
image_url:Optional[str] = None
thread_id:str
python
#./app/common/logger.py
#日志的处理 时间-级别-模块-消息
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(name)s - %(message)s"
def setup_logging():
logging.basicConfig(
level = logging.INFO,
format = LOG_FORMAT,
handlers = [
logging.StreamHandler(sys.stdout), #输出到控制台
#logging.FileHandler("app.log") #如果需要存到文件可以开启
]
)
#创建一个全局的logger 实例
logger = logging.getLogger("personal_chief")
python
# 该内容放在./app/agents/personal_chief.py
from app.common.logger import logger
from langchain.mesage import HumanMessage,AIMessage,AIMessageChunk
#流式对话
async def search_recipes(prompt: str, image: str, thread_id: str):
"""调用agent搜索食谱"""
logger.info(f"[用户]: {prompt}, image: {image}, thread_id: {thread_id}")
try:
# 判断是否有图片,封装不同格式的消息
if not image or image.strip() == "":
message = HumanMessage(content=prompt)
else:
message = HumanMessage(content=[
{"type": "image", "url": image},
{"type": "text", "text": prompt}
])
# 流式调用Agent
for chunk, metadata in agent.stream(
input: {"messages": [message]},
config: {"configurable": {"thread_id": thread_id}},
stream_mode="messages"
):
if isinstance(chunk, AIMessageChunk) and chunk.content:
yield chunk.content
except Exception as e:
logger.error(f"[错误]: {str(e)}")
yield "信息检索失败,试看手动输入食物列表?"
# 清空会话
def clear_messages(thread_id: str):
"""清空会话"""
logger.info(f"清空历史消息, thread_id: {thread_id}")
checkpointer.delete_thread(thread_id)
# 查询会话历史
def get_messages(thread_id: str) -> list[dict[str, str]]:
"""获取会话历史"""
logger.info(f"获取历史消息,thread_id: {thread_id}")
# 根据 thread_id 查询 checkpoint
checkpoint = checkpointer.get({"configurable": {"thread_id": thread_id}})
# 如果不存在,返回空列表
if not checkpoint:
return []
# 安全获取 messages
channel_values = checkpoint.get("channel_values")
if not channel_values:
return []
messages = channel_values.get("messages", [])
if not messages:
return []
# 转换消息格式
result = []
for msg in messages:
if not msg.content:
continue
if isinstance(msg, HumanMessage):
result.append({"role": "user", "content": msg.content})
elif isinstance(msg, AIMessage):
result.append({"role": "assistant", "content": msg.content})
return result
流式调用
python
from langchain.messages import AIMessageChunk
for chunk, metadata in agent.stream(
{"messages": [multимодal_message]},
config,
stream_mode="messages"
):
if isinstance(chunk, AIMessageChunk) and chunk.content:
print(chunk.content, end="", flush=True)
获取会话历史
python
checkpointer.get(config)
for m in checkpointer.get(config)['channel_values']['messages']:
print(type(m))
print(m)
#便捷的获取会话历史的函数
from langchain.messages import AIMessage
def get_messages(thread_id: str) -> list[dict[str, str]]:
"""获取会话历史"""
# 根据 thread_id 查询 checkpoint
cp = checkpointer.get({"configurable": {"thread_id": thread_id}})
# 如果不存在,返回空列表
if not cp:
return []
# 安全获取 messages
channel_values = cp.get("channel_values")
if not channel_values:
return []
messages = channel_values.get("messages", [])
if not messages:
return []
# 转换消息格式
result = []
for msg in messages:
if not msg.content:
continue
if isinstance(msg, HumanMessage):
result.append({"role": "user", "content": msg.content})
elif isinstance(msg, AIMessage):
result.append({"role": "assistant", "content": msg.content})
return result
清空会话历史
checkpointer.delete_thread("6")