【LangChain 开发】LangChain——提示词优化


🚀 欢迎来到我的CSDN博客:Optimistic _ chen
一名热爱技术与分享的全栈开发者,在这里记录成长,专注分享编程技术与实战经验,助力你的技术成长之路,与你共同进步!


🚀我的专栏推荐

专栏内容特色适合人群
🔥C语言从入门到精通系统讲解基础语法、指针、内存管理、项目实战零基础新手、考研党、复习
🔥Java基础语法系统解释了基础语法、类与对象、继承Java初学者
🔥Java核心技术面向对象、集合框架、多线程、网络编程、新特性解析有一定语法基础的开发者
🔥Java EE 进阶实战Servlet、JSP、SpringBoot、MyBatis、项目案例拆解想快速入门Java Web开发的同学
🔥Java数据结构与算法图解数据结构、LeetCode刷题解析、大厂面试算法题面试备战、算法爱好者、计算机专业学生
🔥Redis系列从数据类型到核心特性解析项目必备

🚀我的承诺:
✅ 文章配套代码:每篇技术文章都提供完整的可运行代码示例

✅ 持续更新:专栏内容定期更新,紧跟技术趋势

✅ 答疑交流:欢迎在文章评论区留言讨论,我会及时回复(支持互粉)


🚀 关注我,解锁更多技术干货!
⏳ 每天进步一点点,未来惊艳所有人!✍️ 持续更新中,记得⭐收藏关注⭐不迷路 ✨

📌 标签:#技术博客#编程学习#Java#C语言#算法#程序员

提示词模板

在之前的讨论中,我们介绍了提示词工程技巧,它主要用于设计和优化提示词。而提示词模板则是 LangChain 框架的核心组件之一,在大语言模型(LLM)应用的各个构建环节中都有着广泛的应用。

简单来说:只要是需要动态、批量、有结构的向LLM发送请求的地方,几乎都会用到提示词模板。

字符串模板

PromptTemplate实现了标准的Runnable接口,同样实现提示词模板功能

from langchain_core.prompts import PromptTemplate

prompt_template=PromptTemplate.from_template("翻译为{language}")

print(prompt_template.invoke({"language":"English"}))

在这里插入图片描述

聊天消息模板

ChatPromptTemplate 模板:专为LangChain聊天模型设计。可以更方便的构建包含SystemMessage、HumanMessage、AIMessage的消息模板

from langchain.chat_models import init_chat_model
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

model = init_chat_model("deepseek-v4-pro", model_provider="deepseek")
#设置模板
prompt_template=ChatPromptTemplate(
    [
        ("system","翻译为{language}"),
        ("user","{text}")
    ]
)
#实例化模板
messagesValue=prompt_template.invoke(
    {
        "language":"English",
        "text":"你是谁"
    }
)
messages=messagesValue.to_messages()

#输出解析
parser=StrOutputParser()
chain=model|parser
print(chain.invoke(messages))

在这里插入图片描述

特定位置插入消息列表

MessagesPlaceholder 负责在特定位置添加消息列表.

from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# 1. 创建模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一位乐于助人的助手。"),
    # 使用 MessagesPlaceholder 预留一个位置,变量名为 "history"
    MessagesPlaceholder(variable_name="history"),
    ("human", "{input}"),
])

# 2. 准备对话历史 (一个消息列表)
from langchain_core.messages import HumanMessage, AIMessage

chat_history = [
    HumanMessage(content="你好!"),
    AIMessage(content="你好!今天想聊点什么呢?"),
]

# 3. 填充模板,生成最终的提示词
final_prompt = prompt.invoke({
    "history": chat_history,  # 将历史消息列表传给 "history" 变量
    "input": "我想了解一下 LangChain。", # 当前用户输入
})

print(final_prompt)

在这里插入图片描述

使用写好的提示词模板

LangChain Hub是⼀个⽤于上传、浏览、拉取和管理提⽰词(prompts)的地⽅,而Prompt Maker 模板是⼀个【提⽰⽣成器】,它可以⾃动化优化提⽰的过程,从⽽提⾼语⾔模型在各种应⽤中的质量和效果

from langchain.chat_models import init_chat_model
from langsmith import Client


#创建 LangSmith 客户端
client=Client()
#从 LangSmith 拉取一个名为 "hardkothari/prompt-maker" 的提示模板。
prompt=client.pull_prompt("hardkothari/prompt-maker", include_model=True)

model = init_chat_model("deepseek-v4-pro", model_provider="deepseek")

chain=prompt|model

while True:
    task=input("\n你的需求是什么(输入quit退出)\n")
    if task=="quit":
        break

    lazy_prompt=input("\n当前提示是什么(输入quit退出)\n")
    if lazy_prompt=='quit':
        break

    print("\n Response:")
    chain.invoke({'lazy_prompt':lazy_prompt,'task':task}).pretty_print()

在这里插入图片描述

少样本提示

少样本提示是一种通过向LLM提供少量具体样本,来“教”它们如何执行某些特定任务的技术。这是提高LLM理解能力最有效的方法之一。

给我样本实例:

examples=[
		{"input":"2$2","output":"4"},
		{"input":"2$3","output":"5"},
]

接下来我们需要将⽰例集实例化成聊天模型可以读懂的聊天消息,对于LangChain就需要创建应该FewShotChatMessagePromptTemplate对象来实例化示例。

FewShotChatMessagePromptTemplate是一个提示词模板,专门用来将示例集实例化为聊天消息

from langchain.chat_models import init_chat_model
from langchain_core.prompts import FewShotChatMessagePromptTemplate, ChatPromptTemplate

# 1. 定义示例数据(每个示例是一个字典)
examples = [
    {"input": "2$2", "output": "4"},
    {"input": "2$3", "output": "5"},
]

# 2. 定义每个示例的格式化模板
#    使用 from_messages 创建消息列表,包含人机对话
example_prompt = ChatPromptTemplate.from_messages(
    [
        ("human", "{input}"),
        ("ai", "{output}"),
    ]
)

# 3. 创建 FewShotChatMessagePromptTemplate
few_shot_prompt = FewShotChatMessagePromptTemplate(
    example_prompt=example_prompt,
    examples=examples,
)

# 4. 调用并打印结果(无需额外输入)
print(few_shot_prompt.invoke({}).to_messages())

final_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个算术助手。"),
        few_shot_prompt,
        ("human", "{input}"),
    ]
)
model=model = init_chat_model("deepseek-v4-pro", model_provider="deepseek")
chain=final_prompt|model
chain.invoke({"input":"7$8?"}).pretty_print()

在这里插入图片描述

示例增强信息提取能力

第一步定义结构化对象
第二步定义两个关键示例,每个示例包括文本和期待输出
第三步定义提示词模板
第四步构造请求的消息列表,遍历每对示例,使用tool_example_to_messages转换格式,将每个实例转换为LLM可理解的消息格式
第五步初始化模型并绑定结构化输出模式,最后构件链,并调⽤

from typing import List, Optional

from langchain.chat_models import init_chat_model
from pydantic import BaseModel, Field
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
from langchain_deepseek import ChatDeepSeek
import uuid

# 1. 定义结构化返回对象
class Person(BaseModel):
    name: Optional[str] = Field(default=None, description="人物的姓名")
    hair_color: Optional[str] = Field(default=None, description="人物的头发颜色")
    height_in_meters: Optional[str] = Field(default=None, description="人物的身高(单位:米)")

class ExtractedData(BaseModel):
    people: List[Person] = Field(description="从文本中提取的人物信息列表")

# 2. 定义两个关键示例
example1 = {"input": "今天天气真好。", "output": ExtractedData(people=[])}
example2 = {
    "input": "张飞的头发是黑色的,身高1.8米。李逵的头发和张飞的颜色一样。",
    "output": ExtractedData(people=[
        Person(name='张飞', hair_color='黑色', height_in_meters='1.80'),
        Person(name='李逵', hair_color='黑色', height_in_meters=None)
    ])
}
examples = [example1, example2]

# 3. 定义提示词模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业的信息提取算法。仅从文本中提取相关信息。如果你不知道被要求提取的属性的值,请将该属性的值设为 null。"),
    MessagesPlaceholder("examples"),
    ("human", "{text}"),
])

# 4. 构造请求的消息列表
def tool_example_to_messages(example):
    """将示例转换为消息列表"""
    messages = [HumanMessage(content=example["input"])]
    tool_calls = [{
        "id": str(uuid.uuid4()),
        "args": example["output"].dict(),
        "name": "ExtractedData",
    }]
    messages.append(AIMessage(content="", tool_calls=tool_calls))
    messages.append(ToolMessage(
        content=example["output"].json(),
        tool_call_id=tool_calls[0]["id"]
    ))
    return messages

example_messages = []
for ex in examples:
    example_messages.extend(tool_example_to_messages(ex))


# 5. 初始化模型,绑定结构化输出,构造链并调用
model = init_chat_model(
    "deepseek-v4-pro",
    model_provider="deepseek",
    model_kwargs={
        "extra_body": {"thinking": {"type": "disabled"}}
    }
)
structured_llm = model.with_structured_output(ExtractedData)
chain = prompt | structured_llm

test_text = "赵子龙身高1.8米,留着乌黑长发飘逸。威风凛凛,在曹营三进三出"
result = chain.invoke({"text": test_text, "examples": example_messages})

print(result)

在这里插入图片描述

示例选择器

⼀旦我们有了⽰例数据集,就需要考虑提⽰中应该有多少个⽰例。关键的权衡是,更多的⽰例通常会提⾼性能,但更⼤的提⽰会增加成本和延迟。超过某个阈值,太多⽰例可能会开始混淆模型。最佳的⽅法是使⽤不同数量的⽰例进⾏⼀些实验

在LangChain中,⽰例选择器就可以帮我们从⼀组【⽰例的集合】中根据具体策略选择正确的【⽰例⼦集】构建少样本提⽰
目前有这些策略可供选择:

  1. Length:根据特定长度内可以容纳的数量选择示例
  2. Similarity:使用输入和示例之间的语义相似性来决定选择哪些示例
  3. MMR:使⽤输⼊和⽰例之间的【最⼤边际相关性】来决定要选择哪些⽰例。
  4. Ngram:使⽤输⼊和⽰例之间的【ngram重叠】来决定要选择哪些⽰例。

按照长度选择示例

当我们担⼼构造提⽰时,将超过上下⽂窗⼝⻓度,根据特定⻓度内可以容纳的数量选择⽰例。对于较⻓的输⼊,它将选择更少的⽰例来包含;⽽对于较短的输⼊,它将选择更多⽰例。

按⻓度选择⽰例LengthBasedExampleSelector类:
在这里插入图片描述

按照语义相似性选择示例(Similarity)

什么是语义相似?它是衡量⽂本在【含义上】的接近程度。LangChain 能根据输⼊和⽰例之间的语义相似性来决定选择哪些⽰例,它通过查找与输⼊具有最⼤余弦相似性的嵌⼊⽰例来实现这⼀点。
SemanticSimilarityExampleSelector:语义相似性选择⽰例类
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
LLM按照输入的语义,在示例中选择相似的语义去“学习”

按最⼤边际相关性选择⽰例(MMR)

最⼤边际相关性:它是⼀种重新排序算法,它使⽤语义相似性作为基础⼯具,从⼀个候选集中挑选出⼀组既能代表查询主题⼜彼此多样化的结果。

类似于短视频推荐:推荐与⽤⼾兴趣相关但⼜不同类型的物品,避免“信息茧房”。RAG(检索增强⽣成):在从知识库检索完⼀堆相关⽂档后,使⽤MMR进⾏去重和多样化筛选,再交给LLM⽣成答案,能有效提升答案质量和减少幻觉
在这里插入图片描述
选择和输入语义相关的示例,再选择和输入语义最大边际相关的示例。

通过ngram重叠选择⽰例(Ngram)

ngram指⼀个⽂本序列中连续的n个词(word)或字符(character)
ngram重叠:通过计算它们之间共同拥有的ngram数量来⼀种衡量两段⽂本相似度的⽅法。

text1:苹果手机很好用 (苹果 手机 很 好用)
text2:这个手机很好用 (这个 手机 很 好用)
这两段⽂本单词重复度很⾼,连续三个词的相同的情况也存在,因此ngram重叠⾼

text1 = 苹果⼿机很好⽤" (分词后:苹果 手机 很 好⽤)
text2 = “iPhone ⾮常不错” (分词后:iPhone ⾮常 不错 )
这两段⽂本在含义上⾮常相似,但它们的ngram重叠度为0

语义ngram重叠:不再⽐较词本⾝,⽽是⽐较词背后的语义向量(Embedding)

text1 = 苹果⼿机很好⽤" (分词后:苹果 手机 很 好⽤)
text2 = “iPhone ⾮常不错” (分词后:iPhone ⾮常 不错 )
通过计算每个分词的向量相似度,最终语义上ngram重叠度很高

语义ngram重叠常⽤于需要更精准语义评估的场景,NGramOverlapExampleSelector类:在这里插入图片描述

完结撒花!🎉

如果这篇博客对你有帮助,不妨点个赞支持一下吧!👍
你的鼓励是我创作的最大动力~

想获取更多干货? 欢迎关注我的专栏 → optimistic_chen
📌 收藏本文,下次需要时不迷路!

我们下期再见!💫 持续更新中……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Optimistic _ chen

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

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

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

打赏作者

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

抵扣说明:

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

余额充值