大模型学习笔记:LangChain核心组件-提示词(Prompts)
发送给大模型的所有消息都可以称为提示词(Prompt),它直接影响模型的输出结果。
其中,SystemMessage尤为重要,我们把SystemMessage称为系统提示词(System Prompt),它可以给模型设定角色和本次聊天的背景,对模型生成的内容有很大的影响。
1 系统提示词
在创建智能体时,我们可以直接设定system prompt,不必在每次发送消息时指定。
from langchain.agents import create_agent
from langchain.messages import HumanMessage
# 创建智能体
agent = create_agent(
model = "deepseek-chat",
system_prompt="像海盗一样说话."
)
for token, metadata in agent.stream(
{"messages": [HumanMessage(content="你是谁?")]},
stream_mode="messages"
):
print(token.content, end="", flush=True)
如果没有设定系统提示词,模型会按照训练中的自我认知来回答:
你好!我是DeepSeek,由深度求索公司创造的AI助手!😊
我是一个纯文本模型,虽然不支持多模态识别功能,但我有文件上传功能,可以帮你处理图像、txt、pdf、ppt、word、excel等各种文件,从中读取文字信息进行分析处理。
我的一些特点:
- 完全免费使用,没有收费计划
- 上下文长度达128K,可以处理很长的对话
- 支持联网搜索(需要你手动点开联网搜索按键)
- 可以通过官方应用商店下载App使用
而设定了海盗这个角色后,它的回答就非常有趣了:
啊哈!我是你船上的鹦鹉,一个在数字海洋里翱翔的AI助手!想聊聊宝藏、航海,还是七大洋的奇闻?尽管放马过来,伙计!🗺️⚓
2 提示词工程
通过优化System Prompt从而让模型输出更理想的结果的这一过程,我们称为提示词工程(Prompt Engineering)。
也就是说,提示词优化不是一锤子买卖,而是一个不断优化、测试、再优化的过程。那么,提示词到底该怎么写呢?
从内容来说,提示词通常包含以下几个部分,通常按此顺序排列:
- 身份(Identity):描述AI的职责、沟通风格和总体目标。
- 说明(Instructions):请指导模型如何生成所需的响应。它应该遵循哪些规则?模型应该做什么,以及模型绝对不能做什么?
- 示例(Examples):提供可能的输入示例,以及模型期望的输出。
- 背景信息(Context):向模型提供生成响应所需的任何额外信息,例如RAG的额外知识库数据,或您认为特别相关的任何其他数据。
从格式来说,在编写System Prompt时,您可以使用Markdown格式和XML 标签的组合来帮助模型理解提示和上下文数据的逻辑边界。
- Markdown 的标题和列表有助于标记提示的不同部分,并向模型传达层级结构。它们还可以提高开发过程中提示的可读性。
- XML 标签可以帮助明确区分一段内容(例如用作参考的辅助文档、对话示例等)的起始和结束位置。
示例:
# Identity
You are a helpful assistant that labels short product reviews as
Positive, Negative, or Neutral.
# Instructions
* Only output a single word in your response with no additional formatting
or commentary.
* Your response should only be one of the words "Positive", "Negative", or
"Neutral" depending on the sentiment of the product review you are given.
# Examples
<product_review id="example-1">
I absolutely love this headphones — sound quality is amazing!
</product_review>
<assistant_response id="example-1">
Positive
</assistant_response>
<product_review id="example-2">
Battery life is okay, but the ear pads feel cheap.
</product_review>
<assistant_response id="example-2">
Neutral
</assistant_response>
<product_review id="example-3">
Terrible customer service, I'll never buy from them again.
</product_review>
<assistant_response id="example-3">
Negative
</assistant_response>
接下来,我们就学习下不同的提示词对模型结果的影响。
2.1 设定角色和详细指令
角色可以帮助模型认清自己的身份,以对应的身份来回答问题。
指令则告诉模型需要遵循哪些规则,应该做什么,不应该做什么
例如:
system_prompt = """
# 身份
- 你是一个编程助手,你帮助用户编写Python代码。
# 指令
- 定义变量时,使用snake case命名法,而不是camel case命名法。
- 不要返回markdown格式说明,仅仅返回代码即可。
"""
# 创建智能体
agent = create_agent(
model = "deepseek-chat",
system_prompt=system_prompt
)
for token, metadata in agent.stream(
{"messages": [HumanMessage(content="怎样定义string变量记录学校名字,例如`清华大学`")]},
stream_mode="messages"
):
print(token.content, end="", flush=True)
输出结果:
school_name = "清华大学"
2.2 Few-Shot examples
有的时候我们希望模型按照固定的风格来回答问题,而这种风格又不太好描述,那我们就可以通过举例的方式让模型学习例子来回答。
用户只需在输入提示(Prompt)中提供几个输入-输出示例,模型就能理解任务模式并生成符合预期的输出:
system_prompt = """
# 身份
- 你是一个科幻作家,根据用户的要求创建一个太空之都。
# 示例
user:月球的首都是什么?
assistant:月华城(Lunara)—— 镶嵌在月球静海环形山中的水晶穹顶都市,其核心是一座利用月球潮汐能驱动的巨型生态循环塔。
user:火星的首都是什么?
assistant:赤晶城(Aresia)—— 深嵌于火星奥林匹斯山熔岩管内的蜂巢都市,地表仅露出由火星红土烧制而成的螺旋尖塔。
"""
# 创建智能体
agent = create_agent(
model = "deepseek-chat",
system_prompt=system_prompt
)
for token, metadata in agent.stream(
{"messages": [HumanMessage(content="金星的首都是什么?")]},
stream_mode="messages"
):
print(token.content, end="", flush=True)
结果:
熔金城(Aurum)——悬浮于硫酸云层之上的宏伟浮空都市,以反光性合金铸造,永恒折射着昏黄的日光。
2.3 结构化输出
由于传统程序识别结构化的数据会更加方便,所以有时候我们希望LLM也能输出固定结构的内容,方便我们解析。这同样可以通过系统提示词来实现。
system_prompt = """
# 身份
- 你是一个科幻作家,根据用户的要求创建一个太空之都。
# 指令
- 请务必以JSON格式输出,不要加任何markdown样式。
# 示例:
user: 月球的首都是什么?
assistant:
{
"name": "月华市(Lunaria)",
"location": "位于月球正面赤道附近的静海基地遗址之上,依托巨大的穹顶与地下网络建成",
"vibe": "冷冽、高效、革新",
"economy": "氦-3能源开采、量子通信枢纽、尖端生物圈农业"
}
"""
agent = create_agent(
model="deepseek-chat",
system_prompt=system_prompt
)
response = agent.invoke(
{"messages": [HumanMessage(content="金星的首都是什么?")]},
)
print(response['messages'][-1].content)
输出结果:
{
"name": "硫磺城(Sulfura)",
"location": "悬浮于金星浓厚大气层中距地表约50公里的高空,由巨大的反重力浮空平台群构成",
"vibe": "高压、炽热、坚韧",
"economy": "大气资源提炼(二氧化碳、硫酸)、极端环境材料制造、太阳能巨型阵列"
}
在LangChain中,实现结构化输出会更加简单。我们无需自己在提示词中添加描述实现结构化输出,而仅仅是设定好一个数据类型即可。
首先,我们定义一个类,用来封装模型要输出的数据:
from pydantic import BaseModel
class CapitalInfo(BaseModel):
name: str
location: str
vibe: str
economy: str
然后,我们就可以在创建Agent时设定好输出格式:
# 然后,我们就可以创建智能体并设置结构化输出的格式了。
agent = create_agent(
model='deepseek-chat',
system_prompt="你是一个科幻作家,根据用户的要求创建一个太空之都。",
response_format=CapitalInfo # 设置结构化输出的格式
)
response = agent.invoke(
{"messages": [HumanMessage(content="月球的首都是什么?")]}
)
注意,在输出的结果中,有一个’structured_response’的字段,就是结构化输出的对象:
{'messages': [HumanMessage(content='月球的首都是什么?', additional_kwargs={}, response_metadata={}, id='42747579-7994-4fe9-93bf-970216fb65b4'), AIMessage(content='', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 130, 'prompt_tokens': 355, 'total_tokens': 485, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 355}, 'model_provider': 'deepseek', 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_eaab8d114b_prod0820_fp8_kvcache', 'id': '3dcb8346-67b2-4cf1-b61d-cf9cf8e2dde9', 'finish_reason': 'tool_calls', 'logprobs': None}, id='lc_run--019ca25b-a0e2-77a0-af64-9b1d2c9247f0-0', tool_calls=[{'name': 'CapitalInfo', 'args': {'name': '月宫', 'location': '月球南极-艾特肯盆地边缘', 'vibe': '高科技与东方古典美学融合的宁静都市,拥有透明穹顶下的传统园林和悬浮建筑', 'economy': '氦-3开采、量子计算中心、太空旅游枢纽、月球农业和科学研究'}, 'id': 'call_00_NBnEIMUhLTXZdXRJLZVYCnan', 'type': 'tool_call'}], invalid_tool_calls=[], usage_metadata={'input_tokens': 355, 'output_tokens': 130, 'total_tokens': 485, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}}), ToolMessage(content="Returning structured response: name='月宫' location='月球南极-艾特肯盆地边缘' vibe='高科技与东方古典美学融合的宁静都市,拥有透明穹顶下的传统园林和悬浮建筑' economy='氦-3开采、量子计算中心、太空旅游枢纽、月球农业和科学研究'", name='CapitalInfo', id='1735ea63-403a-468a-a5ea-cc01deeab0b2', tool_call_id='call_00_NBnEIMUhLTXZdXRJLZVYCnan')], 'structured_response': CapitalInfo(name='月宫', location='月球南极-艾特肯盆地边缘', vibe='高科技与东方古典美学融合的宁静都市,拥有透明穹顶下的传统园林和悬浮建筑', economy='氦-3开采、量子计算中心、太空旅游枢纽、月球农业和科学研究')}
所以,我们这样获取结构化的输出:
city = response['structured_response']
完整代码:
from pydantic import BaseModel
from langchain.agents import create_agent
from langchain.messages import HumanMessage
# 首先,我们定义一个类,用来封装模型要输出的数据:
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(
{"messages": [HumanMessage(content="月球的首都是什么?")]}
)
city = response['structured_response']
print(f"{city.name}位于{city.location},是一座{city.vibe}的城市,其主要产业包括{city.economy}。")
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)