LangChain1.2学习第三章—— LangSmith、提示词模板、历史对话、消息

 说明:本套资源源于B站尚硅谷教程,视频链接:https://www.bilibili.com/video/BV1rv7A6oEeP?spm_id_from=333.788.videopod.episodes&vd_source=bba5be243325ecee1f55ec265557fedd

第一章内容:LangChain1.2学习第一章——知识储备-CSDN博客

第二章内容:LangChain1.2学习第二章—— 调用大模型-CSDN博客

目录

一、LangSmith概述

1.1 具体功能

二、调用大模型,查看监控指标

三、认识消息

3.1 消息的内部结构

3.2 消息的类型

3.3 消息格式

3.4 开发示例

3.5 实战练习

3.5.1 对话历史管理

3.5.2 优化对话历史

3.5.3 多轮对话—聊天机器人

四、提示词模板—Prompt Templates

4.1 为什么推荐提示词模板?

4.2 ChatPromptTemplate的使用

4.2.1 方式1:调用from_messages()——推荐

4.2.2 方式2:使用实例初始化方法

4.3 模板调用的3种方式

4.3.1 invoke()-返回ChatPromptValue

4.3.2 使用format()—返回字符串

4.3.3 使用format_messages()—返回消息列表

4.3.4 调用大模型接口

4.4 丰富的初始化参数类型

4.4.1 str列表类型

4.4.2 tuple列表类型

4.4.3 dict列表类型

4.4.4 Message列表类型

4.4.5 MessagePromptTemplate列表类型

4.4.6 BaseChatPromptTemplate列表类型

五、高级特性

5.1 部分变量预填充:partial()


一、LangSmith概述

LangSmith 是 LangChain 生态系统中专门用于 LLM(大语言模型)应用调试、监控、评估和管理 的平台。

  • 追踪(tracing):记录每次 LLM 调用的详细信息
  • 监控(monitoring):实时查看应用性能
  • 调试(debug):排查问题和优化性能
  • 评估(evaluate):系统化测试 LLM 应用

1.1 具体功能

功能1:核心应用与开发

Tracing(追踪):

  • 功能:这是 LangSmith 最核心的功能。它会完整记录你大模型应用的每一次调用链路(Trace)。
  • 当你的 Agent(智能体)或 RAG 系统运行变慢或报错时,点击进入对应的项目,你可以看到每一步具体的 Prompt 是什么、模型返回了什么、消耗了 多少 Token,以及每一个链条节点的耗时,非常方便排查 Bug 和优化性能。

Monitoring(监控):

  • 功能:提供生产环境的高级数据可视化看板。
  • 作用:帮你从宏观角度监控应用在一段时间内的运行状况。你可以看到 Token 消耗趋势、 QPS(每秒请求数)、错误率、平均延迟(Latency)以及成本预估。适合应用上线后观察系统的 稳定性和开销。

Datasets & Experiments(数据集与实验):

  • 功能:用于管理测试数据集并运行对比实验。
  • 作用:你可以把用户的真实输入、特定的边界情况(Edge Cases)存为数据集。当你修改了 Prompt 或更换了底层大模型时,可以在这里运行自动化对比测试,直观看到新旧版本在同一批测 试集上的表现差异。

Evaluators(评估器):

  • 功能:配置和自动化评估任务。
  • 作用:大模型的输出往往难以用传统的断言(Assert)来测试。这里允许你配置基于规则(如关键 词匹配)或基于模型(LLM-as-a-judge)的评估指标(如:答案相关性、是否包含幻觉等),对追 踪到的数据或实验结果进行自动打分。

Annotation Queues(标注队列):

  • 功能:人工反馈与数据清洗工具。
  • 作用:在应用开发或初上线阶段,你可以把一部分痕迹(Traces)发送到标注队列中,让团队中的 核心成员、业务专家或人工客服进行手动打分、纠正回答或贴标签,这些高质量的人工标注数据后 续可直接用于微调模型或充当测试集。

功能2:提示词与调试工具

Prompts(提示词管理):

  • 功能:类似“提示词版的 GitHub”。
  • 作用:把 Prompt 从代码中解耦出来,统一在云端管理。你可以在这里对 Prompt 进行版本控制 (如 v1、v2),直接在代码中通过 API 动态拉取最新的提示词。它还支持团队协作和 Prompt 的分享。

Playground(演练场):

  • 功能:一个网页端的模型交互界面。
  • 作用:无需写任何代码,直接在这里选择不同的模型(如 OpenAI、Anthropic 或是本地模型), 快速微调并测试你的 Prompt 效果,还可以一键将调整好的 Prompt 保存到上方的 Prompts 仓库 中。

Studio(工作室):

  • 功能:通常与 LangGraph 深度集成,提供可视化的图形交互界面。
  • 作用:如果你的应用是基于图结构(Graph-based)的复杂复杂 Agent 架构,Studio 可以让你可 视化地看到状态机(State)在各个节点之间的流转,甚至支持在某个节点“暂停”,手动修改数据 后再继续向下执行,是调试复杂智能体交互的利器。

Context Hub(上下文中心):

  • 功能:管理全局上下文或通用组件配置。
  • 作用:用于存放可在多个项目或 Prompt 中复用的公共上下文模板、全局变量或系统预设提示。

功能3:部署与沙盒

Deployments(部署):

  • 功能:一键将你的 LangChain 应用或 LangGraph Agent 部署为线上可用的 API 服务(通常依托于 LangGraph Cloud)。
  • 作用:提供开箱即用的生产端点,帮你处理高并发、队列管理和状态持久化,让你专注于编写业务 逻辑。

Sandboxes(沙盒):

  • 功能:提供轻量级的在线运行和测试环境。
  • 作用:在不污染生产环境的前提下,供开发人员安全地试运行、测试新部署的 Agent 或执行自动化 脚本。

建议:现阶段大家可以重点关注 Tracing(观察你的项目里的调用细节)和 Playground(快速调 优提示词)。当你的应用结构开始走向复杂(比如引入了复杂的 RAG 检索或多 Agent 协同)时, 再逐步引入 Datasets 进行量化评估,并利用 Studio 进行可视化调试。

二、调用大模型,查看监控指标

账号准备:请自行到LangSmith申请API-KEY。

修改.env 配置文件

# 是否启用Langsmith监控功能

LANGSMITH_TRACING=true

# Langsmith监控WebUI地址

LANGSMITH_ENDPOINT=https://api.smith.LangChain.com

# 创建的API_KEY
LANGSMITH_API_KEY=xxx

# 自定义项目名称,可以在Langsmith WebUI监控页面根据名称查看对应的运行记录
LANGSMITH_PROJECT="langsmith-test"
from langchain_qwq import ChatQwen
from dotenv import load_dotenv
import os
load_dotenv(override=True)
qwen_model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
messages = [
    "请介绍侯莫陈崇",
    "在平定安史之乱中,谁的功能最大",
    "秦始皇的功与过"
]
response = qwen_model.batch_as_completed(messages)
for result in response:
    print(f" {result}")

本地运行后,查看监控指标

具体监控请自行学习

三、认识消息

大模型没有记忆,它的输出只和输入模型的内容有关(上下文)。很多大模型API服务也没有在服务端维 护会话历史,是“ 无状态”的。因此,如果应用需要“记住”对话历史,需要在程序中维护消息列表。

在 LangChain 中,Message(消息)是模型交互的最基本单元。它既代表模型接收到的 (Input) ,也代表模型生成的 输出(Output) 。

每一轮与大模型的对话,都由一条或多条 Message 构成。每个 Message 不仅包含 文字内容,还 携带描述上下文状态的 元信息(metadata) ,用于保持对话的一致性和可追踪性。比如,模型 在多轮交互中理解“谁在说话”、“说了什么”、“这条信息属于哪一轮对话”。

LangChain 在 1.0 中提供了跨模型统一的 Message 标准。无论你使用的是 OpenAI、Anthropic、 Gemini 还是本地模型,这一标准都能保持一致的行为。好处:

  • 兼容性强:不同模型的消息格式自动对齐。
  • 可扩展性高:方便添加多模态内容或自定义字段。
  • 可追踪性好:为 LangSmith 等调试工具提供一致的上下文数据结构。

3.1 消息的内部结构

LangChain的消息(Message)对象包含三种字段:

  • Role:消息所属的角色或类型,如 system 、user、assistant。
  • Content:消息内容
  • Metadata:(可选)元数据,存储额外信息。如:消息ID、响应时间、token消耗量、消息标签等。

3.2 消息的类型

LangChain定义了很多消息类型,通过 role 区分。常用的有四种。

1、系统消息

也称为系统提示词,用于在对话开始时为模型设定角色、行为准则和上下文背景。它像是给AI助手的一 份工作说明书,决定了其回答问题的风格、领域和专业范围。

{"role": "system", "content": "你是个精通编程的软件架构师"}

2、用户消息

也称为用户提示词,在多轮对话中,它表示用户的一次输入。可以包含简单的文本问题,也可以是复杂 的多模态内容(如图片、音频、文档等)。

{"role": "user", "content": "你好啊~"}

3、助手(AI)消息

代表模型的回复,包括生成的文本、工具调用、元数据等。

{"role": "assistant", "content": "我也很高兴认识你"}

4、工具调用消息

工具调用结果匹配的消息类型。将此消息返回给模型,让模型基于这个结果继续生成回复。在Tools一节 详细介绍。

{"role": "tool",

"content": "今天天气很好",

"tool_call_id": "call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s"}

问题:为什么使用不同的消息类型?

  • 明确角色:清晰区分系统提示、用户输入和 AI 回复
  • 控制行为:通过 SystemMessage 精确控制 AI 的行为
  • 对话历史:构建完整的多轮对话上下文
  • 调试友好:更容易追踪和调试对话流程

3.3 消息格式

LangChain支持两种消息格式。

格式1:JSON格式

1、系统消息

{"role": "system", "content": "你是个善解人意的助手"}

2、用户消息

{"role": "user", "content": "你好啊~"}

3、助手消息

{"role": "assistant", "content": "我也很高兴认识你"}

4、工具调用消息

{"role": "tool",

"content": "",

"tool_call_id": "call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s"}

格式2:

1、系统消息

SystemMessage(content="你是个善解人意的助手")

2、用户消息

HumanMessage(content="你好啊~")

3、助手消息

AIMessage("我也很高兴认识你")

4、工具调用消息

ToolMessage(  

 content="",    

tool_call_id="call_00_nUD2NC9QRN5Cg1GaoIkBJQ4s"  # 一定要和AI消息中的调用ID匹 配)

示例

from langchain_core.messages import (
    HumanMessage,    # 用户消息
    AIMessage,       # AI 消息
    SystemMessage,   # 系统消息
    ToolMessage      # 工具返回消息
)
# 消息列表示例
messages = [
    SystemMessage(content="你是一个助手"),
    HumanMessage(content="你好"),
    AIMessage(content="你好!有什么可以帮你?"),
    HumanMessage(content="天气怎么样?"),
    AIMessage(content="让我查询一下..."),
    ToolMessage(content="北京:晴天", tool_call_id="call_123"),
    AIMessage(content="北京今天是晴天")
]

小结

3.4 开发示例

json格式

from langchain_qwq import ChatQwen
from dotenv import load_dotenv
import os
load_dotenv(override=True)
model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
messages = [
    {"role":"system","content":"你是一位历史学家。"},
    {"role":"user","content":"你好"},
    {"role":"assistant","content":"你好,我能帮助你什么?"},
    {"role":"user","content":"请简单介绍李弼"}
]
print(model.invoke(messages))

对象格式

from langchain.messages import SystemMessage,HumanMessage,AIMessage
from dotenv import load_dotenv
import os
load_dotenv(override=True)
model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
messages = [
    SystemMessage("你是一位历史学家。"),
    HumanMessage("你好"),
    AIMessage("你想问什么问题?"),
    HumanMessage("请为我介绍于谨")
]
print(model.invoke(messages).content)

3.5 实战练习

3.5.1 对话历史管理

关键规则:每次调用必须传递完整的对话历史!

也就是说:

第 1 轮:

[system, user] → AI回复 → 保存回复

第 2 轮:

[system, user, assistant, user] → AI回复 → 保存回复

第 3 轮:

[system, user, assistant, user, assistant, user] → AI回复

注意:每次对话都要在原有的消息列表中添加新消息,不可重新创建新的列表。

错误示例1:

# 第一次

response1 = model.invoke("我叫张三")

# 第二次(没传历史)

response2 = model.invoke("我叫什么?")  # AI 不记得!

错误示例2:

conversation = [{"role": "user", "content": "问题1"}]

response1 = model.invoke(conversation)

conversation = [{"role": "user", "content": "问题2"}]  # 重新创建!

response2 = model.invoke(conversation)  # 丢失了历史

错误示例3:

conversation = []

conversation.append({"role": "user", "content": "问题1"})

response1 = model.invoke(conversation) # 忘记保存 response1.content! conversation.append({"role": "user", "content": "问题2"})

response2 = model.invoke(conversation)  # AI 不知道之前的回答

正确做法:

conversation = []

# 第一次

conversation.append({"role": "user", "content": "我叫张三"})

response1 = model.invoke(conversation)

# 关键:保存 AI 回复

conversation.append({"role": "assistant", "content": response1.content})

# 第二次(传递完整历史)

conversation.append({"role": "user", "content": "我叫什么?"})

response2 = model.invoke(conversation)  # AI 记得

示例代码:

from langchain.messages import SystemMessage,HumanMessage,AIMessage
from dotenv import load_dotenv
import os
load_dotenv(override=True)
model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
messages = [
    HumanMessage("我叫张三")
]
response1 = model.invoke(messages).content
messages.append(AIMessage(response1))
messages.append(HumanMessage("我叫什么"))
print(model.invoke(messages).content)

3.5.2 优化对话历史

问题:对话历史会越来越长,消耗大量 tokens 和成本。

解决方案:只保留最近 N 轮对话。具体的:

  • 总是保留 system 消息(定义角色)
  • 只保留最近 N 轮对话,丢弃更早的历史

代码:

from langchain.messages import SystemMessage,HumanMessage,AIMessage
from dotenv import load_dotenv
import os

load_dotenv(override=True)
model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
#定义函数,用于保留最近的对话轮数
def keep_recent_messages(messages,max_pairs=3):
    # max_pairs:指定要保留的几轮对话.每轮 = user + assistant
    #分离 system 对话
    system_messages = [m for m in messages if(m.type == "system")]
    #非 system 对话
    other_messages = [m for m in messages if(m.type != "system")]
    # 保留最近2轮对话
    result_messages = other_messages[-(max_pairs * 2):]
    #返回 system + 最近对话
    return system_messages + result_messages

#初始化
messages = [SystemMessage("你是一位Python老师")]
#第一轮对话
messages.append(HumanMessage("请用一句话解释什么是列表"))
r1 = model.invoke(messages).content
# 保存第一轮对话
messages.append(AIMessage(r1))

#第二轮对话
messages.append(HumanMessage("请用一句话解释是什么是字典"))
r2 = model.invoke(messages).content
messages.append(AIMessage(r2))

#第三轮
messages.append(HumanMessage("请解释列表和字典的区别"))
r3 = model.invoke(messages).content
messages.append(AIMessage(r3))
print(f"原始消息数量:{len(messages)}")

#只保留最近两轮对话
result = keep_recent_messages(messages,max_pairs=2)
print(f"优化后的消息数量是:{len(result)}")
print(f"优化后的消息内容是:{result}")

#新一轮提问
messages.append(HumanMessage("我的最后一个问题是什么"))
r4 = model.invoke(messages).content
print(r4)

3.5.3 多轮对话—聊天机器人

from langchain.messages import SystemMessage,HumanMessage,AIMessage
from dotenv import load_dotenv
from langchain_qwq import ChatQwen
import os

load_dotenv(override=True)
model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
#基础配置
MAX_PAIRS_HISTORY = 10
EXIT_WORD = "quit"
#定义函数,用于保留最近的对话轮数
def keep_recent_messages(messages,max_pairs=3):
    # max_pairs:指定要保留的几轮对话.每轮 = user + assistant
    #分离 system 对话
    system_messages = [m for m in messages if(m.type == "system")]
    #非 system 对话
    other_messages = [m for m in messages if(m.type != "system")]
    # 保留最近2轮对话
    result_messages = other_messages[-(max_pairs * 2):]
    #返回 system + 最近对话
    return system_messages + result_messages

messages = [
    SystemMessage("你是一位历史老师,也是一名耐心、友好的智能助手。我会用自然、清晰的方式回答用户问题。")
]
#启动提示
print(f"请输入你的问题,按{EXIT_WORD}退出。")
#多轮对话主循环
i = 1
while True:
    print("\n", "=" * 10, f'-> 第 {i} 轮对话开始 <-', "=" * 10, "\n")
    user_input = input("请输入你的问题:")
    if user_input.lower() == EXIT_WORD:
        print("对话已结束")
        break
    #追加用户信息
    messages.append(HumanMessage(user_input))

    #流式输出
    print("老师说:",end="",flush=True)
    reply_content = ""

    #管理历史记忆
    memory_messages = keep_recent_messages(messages,MAX_PAIRS_HISTORY)
    for chunk in model.stream(memory_messages):
        if chunk.content:
            print(chunk.content,end="",flush=True)
            reply_content += chunk.content
    print("\n", "=" * 10, f'-> 第 {i} 轮对话结束 <-', "=" * 10, "\n")
    i += 1
    #追加AI回复
    messages.append(AIMessage(reply_content))

四、提示词模板—Prompt Templates

4.1 为什么推荐提示词模板?

在 LangChain 开发中,构造提示词既可以直接使用 Python 字符串拼接(如 f-string、format() 或 +),也可以使用 LangChain 提供的 PromptTemplate或 ChatPromptTemplate。

示例1:字符串拼接方式

# 字符串拼接
topic = "Python"
difficulty = "初学者"
# 难以维护,容易出错
prompt_str = f"你是一个{difficulty}级别的编程导师。请用简单易懂的语言解释{topic}。"
response = model.invoke(prompt_str)
print(f"AI 回复:{response.content}...\n")

优点:

  • 简单直接,上手快
  • 适合临时 demo
  • 无额外学习成本

缺点:

  • 可读性差(变量多时混乱)
  • 不易维护(修改容易出错)
  • 无变量校验(容易漏/拼错)
  • 难以支持复杂场景(多轮对话 / RAG / Few-shot)

示例2:提示词模板

from dotenv import load_dotenv
from langchain_qwq import ChatQwen
from langchain_core.prompts import  ChatPromptTemplate
import os

load_dotenv(override=True)
model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
prompt_template =  ChatPromptTemplate([
    ("system","你是一个AI开发工程师. 你的名字是 {name}"),
    ("user","{user_input}")
])
prompt = prompt_template.invoke({"name":"张三","user_input":"请为我推荐一份Python学习课程"})
print(prompt)

优点:

  • 结构清晰(变量占位)
  • 易维护、可复用
  • 自动变量校验(更安全)
  • 支持复杂场景(对话 / RAG / Agent)
  • 可与 LangChain 生态无缝集成
  • 便于调试与日志追踪

缺点:

  • 有一定学习成本
  • 初期写法略复杂
  • 对极简单场景略“重"

选择建议:

  • 小项目 / 临时用 → 字符串拼接
  • 正式开发 / AI应用 → 提示词模板(必选)

ChatModel+ChatPromptTemplate(输入与输出均为消息列表)

① 模型接口:对应 LangChain 1.0 的主流接口 ChatModel。

② 工作方式:现代聊天模型 API 已原生 支持角色概念。它们不再接受单一字符串, 而是要求输入 一个结构化的消息列表。为构建复杂、可靠的多轮对话智能体系统奠定了坚实的基础。

③ Prompt 工具: ChatPromptTemplate 因此成为LangChain 1.0 中最核心的 Prompt工具。它的职 责是接收变量,并输出一个 List「BaseMessage](消息列表),该列表可直接传递给聊天模型。

4.2 ChatPromptTemplate的使用

在LangChain 1.0中,ChatPromptTemplate 是用于生成消息列表的核心组件。

ChatPromptTemplate是创建 聊天消息列表的提示模板。它比普通 PromptTemplate 更适合处理多角 色、多轮次的对话场景。支持 System / Human /AI 等不同角色的消息模板。

消息类型:

有两种实现方式:

ChatPromptTemplate 可以通过 AI 的回复(用于对话历史) 初始化方法或 from_messages 方法来实例化提示词模板。实例化 时需要传入 messages参数 。常见类型是:tuple构成的列表,参数类型(role : str,content : str )

4.2.1 方式1:调用from_messages()——推荐

该方法允许传入一个由元组(Tuple)构成的列表,列表中的每一个元组都代表一条具有特定角色的消息。

from langchain_core.prompts import ChatPromptTemplate
from dotenv import load_dotenv
from langchain_qwq import ChatQwen
chat_template = ChatPromptTemplate.from_messages(
    [
        ("system","你是一位历史老师,你叫{name}"),
        ("user","你好,你最熟悉哪些历史?"),
        ("ai","我最熟悉西晋历史"),
        ("human","{user_input}")
    ]
)
# 格式化聊天提示词模板中的变量
prompt = chat_template.invoke({"name":"王老师","user_input":"请为我介绍西晋八王之乱"})
print(format(prompt))

4.2.2 方式2:使用实例初始化方法

from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate(
    [
        # {role},{content}的方式
        ("system","你是一位历史老师,你叫{name}"),
        ("user","你好,你最熟悉哪些历史?"),
        ("ai","我最熟悉西晋历史"),
        ("human","{user_input}")
    ]
)
prompt = chat_template.invoke({"name":"王老师","user_input":"请为我介绍西晋八王之乱"})
print(format(prompt))

说明:from_messages()的底层,也是调用的类的__init()__方法

4.3 模板调用的3种方式

对比:invoke()、format()、format_messages()

4.3.1 invoke()-返回ChatPromptValue

from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate(
    [
        # {role},{content}的方式
        ("system","你是一位历史老师,你叫{name}"),
        ("user","你好,你最熟悉哪些历史?"),
        ("ai","我最熟悉西晋历史"),
        ("human","{user_input}")
    ]
)
prompt = chat_template.invoke({"name":"王老师","user_input":"请为我介绍西晋八王之乱"})
print(type(prompt))
print(len(prompt.messages))
print(prompt)

4.3.2 使用format()—返回字符串

from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate(
    [
        # {role},{content}的方式
        ("system","你是一位历史老师,你叫{name}"),
        ("user","你好,你最熟悉哪些历史?"),
        ("ai","我最熟悉西晋历史"),
        ("human","{user_input}")
    ]
)
prompt = chat_template.format(name = "李老师",user_input = "请为我介绍西晋八王之乱")
print(type(prompt))
print(len(prompt))
print(prompt)

4.3.3 使用format_messages()—返回消息列表

from langchain_core.prompts import ChatPromptTemplate
chat_template = ChatPromptTemplate(
    [
        # {role},{content}的方式
        ("system","你是一位历史老师,你叫{name}"),
        ("user","你好,你最熟悉哪些历史?"),
        ("ai","我最熟悉西晋历史"),
        ("human","{user_input}")
    ]
)
prompt = chat_template.format_messages(name = "李老师",user_input = "请为我介绍西晋八王之乱")
print(type(prompt))
print(len(prompt))
print(prompt)

4.3.4 调用大模型接口

from dotenv import load_dotenv
from langchain_qwq import ChatQwen
from langchain_core.prompts import  ChatPromptTemplate
import os

load_dotenv(override=True)
model = ChatQwen(
    model="qwen-plus",
    api_key=os.getenv("QWEN_API_KEY"),
    base_url=os.getenv("QWEN_BASE_URL")
)
chat_template = ChatPromptTemplate(
    [
        # {role},{content}的方式
        ("system","你是一位历史老师,你叫{name}"),
        
        ("human","{user_input}")
    ]
)
prompt = chat_template.format(name = "李老师",user_input = "请为我介绍西晋八王之乱")
result = model.invoke(prompt)
print(result.content)

4.4 丰富的初始化参数类型

前面讲了ChatPromptTemplate的两种创建方式。我们看到不管使用实例初始化方法,还是使用 from_messages(),参数类型都是列表类型。列表中的元素可以是多种类型,前面我们主要测试了元 组类型。

源码:

def __init__(self,
             messages: Sequence[BaseMessagePromptTemplate | BaseMessage | 
BaseChatPromptTemplate | tuple[str | type, str | list[dict] | list[object]] | 
str | dict[str, Any]],
             *,
             template_format: Literal["f-string", "mustache", "jinja2"] = "f
string",
             **kwargs: Any) -> None
@classmethod def from_messages(cls,
messages: Sequence[BaseMessagePromptTemplate | BaseMessage 
| BaseChatPromptTemplate | tuple[str | type, str | list[dict] | list[object]] 
| str | dict[str, Any]],
template_format: Literal["f-string", "mustache", "jinja2"] 
= "f-string")-> ChatPromptTemplate

结论:参数是列表类型,列表的元素可以是字符串、字典、字符串构成的元组、消息类型、提示词模板 类型、消息提示词模板类型等。

4.4.1 str列表类型

列表参数格式是str类型(不推荐),因为默认角色都是human。

#1.导入相关依赖
from langchain_core.prompts import ChatPromptTemplate
# 2.定义聊天提示词模版
chat_template = ChatPromptTemplate.from_messages(
[
"Hello, {name}!"  # 等价于 ("human", "Hello, {name}!")
]
)
# 3. 使用invoke执行
messages = chat_template.invoke({"name":"小谷AI"})
# 4.打印格式化后的聊天提示词模版内容
print(messages)

4.4.2 tuple列表类型

列表参数格式是元组类型

# 示例: 元组形式的消息
prompt = ChatPromptTemplate.from_messages([
("system", "你的名字是{role}."),
("human", "很高兴认识你"),
])
print(prompt.invoke({"role":"小智"}))

4.4.3 dict列表类型

# 示例: 字典形式的消息
prompt = ChatPromptTemplate.from_messages([
{"role": "system", "content": "你的名字是{role}."},
{"role": "human", "content":"很高兴认识你"},
])
print(prompt.invoke({"role":"小智"}))

4.4.4 Message列表类型

from langchain_core.messages import SystemMessage,HumanMessage
chat_prompt_template = ChatPromptTemplate.from_messages([
SystemMessage(content="我是一个贴心的智能助手"),
HumanMessage(content="我的问题是:人工智能英文怎么说?")
])
messages = chat_prompt_template.invoke({})
print(messages)
print(type(messages))

注意:在XxxMessage中不能有占位符。即:

from langchain_core.messages import SystemMessage,HumanMessage
chat_prompt_template = ChatPromptTemplate.from_messages([
SystemMessage(content="我是一个贴心的智能助手"),
HumanMessage(content="我的问题是:{word}英文怎么说?")
])
messages = chat_prompt_template.invoke({"word":"人工智能"})
print(messages)
print(type(messages))

4.4.5 MessagePromptTemplate列表类型

LangChain提供不同类型的MessagePromptTemplate。最常用的是 SystemMessagePromptTemplate HumanMessagePromptTemplate AIMessagePromptTemplate ,分别创建系统消息、人工消息和AI消息。

基本概念:

HumanMessagePromptTemplate,专用于生成 用户消息(HumanMessage) 的模板类

  • 模板化:支持使用变量占位符,可以在运行时填充具体值
  • 格式化:能够将模板与输入变量结合生成最终的聊天消息
  • 输出类型:生成 HumanMessage 对象( content + role="human" )
  • 设计目的 :简化用户输入消息的模板化构造,避免重复定义角色

SystemMessagePromptTemplate、AIMessagePromptTemplate:类似于上面,不再赘述

from langchain_core.prompts import ChatPromptTemplate,SystemMessagePromptTemplate,HumanMessagePromptTemplate,AIMessagePromptTemplate
#创建消息模板
system_message = SystemMessagePromptTemplate.from_template("你是一个{role}")
user_message = HumanMessagePromptTemplate.from_template("请为我解答{content}")
#组装成提示词模板
chat_template = ChatPromptTemplate.from_messages(
    [
    system_message,
    user_message
    ]

)
#格式化提示
formatted_messages = chat_template.invoke({"role":"历史老师","content":"南宋历史"})
print(formatted_messages)

4.4.6 BaseChatPromptTemplate列表类型

使用 BaseChatPromptTemplate,可以理解为ChatPromptTemplate里嵌套了 ChatPromptTemplate。

from langchain_core.prompts import ChatPromptTemplate
message1 = ChatPromptTemplate.from_messages(
    [("system","你是一位{role}")]
)
message2 = ChatPromptTemplate.from_messages(

    [("human","{content}")]
)
message = ChatPromptTemplate.from_messages(
    [message1,message2]
)
result = message.invoke({"role":"历史老师","content":"南宋历史"})
print(result)

五、高级特性

5.1 部分变量预填充:partial()

预填充某些固定不变的变量,创建模板的变体。

使用场景:

  • 某些变量在所有调用中都相同
  • 需要为不同用户/场景创建定制模板
from langchain_core.prompts import ChatPromptTemplate
# 原始模板
template = ChatPromptTemplate.from_messages(
    [("system","你是{role},目标用户是{audience}"),
     ("user","{task}")]
)
# 部分填充
support_template = template.partial(
    role="客服专员",
    audience="消费者"
)

#只需要提供task
message = support_template.invoke({"task":"请退款"})
print(message)

源码直接下载地址: https://pan.quark.cn/s/32a64cc0d812 LKH 算法在中文中的表述为 LKH 算法,它是一种用于处理 TSP(旅行商题)与 VRP(车辆配送题)等组合优化挑战的启发式算法,并且该算法是 Lin-Kernighan 启发式方法的进一步发展。该算法的开发与执行过程具有相当的挑战性,然而,它被认为是获取对称旅行商题最优或接近最优答案的最有效途径之一。LKH 算法的升级版本通过运用灵敏度分析来引导并约束搜索过程,从而使得该算法能够在可接受的时间内为大规模题找出最优解。通过计算实验的验证,证明该方法具备高效性,能够在不足一秒的时间范围内寻得典型100座城市题的最优方案,而对于典型的1000座城市题,也能在不到一分钟的时间框内找到最优解。旅行商题(TSP)是组合优化领域中研究最为深入的课题之一,该题可以通过成本矩阵 C 的特性来进行分类。此题可划分为对称性情形与非对称性情形,同时依据三角不等式的成立与否,可进一步区分为度量性情形与非度量性情形。TSP 的显著地位源于其广泛的实际应用,其中许多应用看似与旅行路径无直接关联。众多现实场景能够以 TSP 的形式来模拟,例如计算机内部布线、车辆路径规划、晶体结构分析、机器人导航控制、印刷电路板打孔定位以及时间表的制定等。TSP 作为一种典型的组合优化课题,其研究对于解决该学科范畴内的其他课题往往具有指导意义。事实上,组合优化领域的诸多突破均可追溯至对 TSP 题的深入探索。计算方法中广为人知的 branch and bound 技术最初便是在 TSP 的研究背景下被引入的。攻克 TSP 所面临的智力难题亦起到了推动作用,该题的表述看似简单,却极难求解。当考虑到可能...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

geminigoth

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值