本笔记主要介绍了生成式大语言模型的基本使用方法、核心技术原理以及提示工程的设计技巧。内容涵盖了从调用API实现简单对话,到自回归预测、预训练和推理,再到提示词工程的各种结构设计和实战技巧,最后还总结了常见的提示工程开发实践资源和面试拷打题目。
注意事项:选用的是qwen,api-key配置到了系统环境变量里,避免在代码里显示调用,安全性更高。
from openai import OpenAI
class QAgent:
def __init__(self, api_key, base_url, system_prompt="你是一个很聪明的智能体。你会用中文回答用户提出的任何问题。"):
self.api_key = os.getenv("qwen") # 从系统环境变量里获取 API Key,安全性更高,避免在代码里显示调用
# self.api_key = api_key # 自己的 API Key,不建议在代码里显示调用,安全性更高,可以配置到系统环境变量里,使用os.getenv("DASH")来获取
self.base_url = base_url # 平台相应的接口地址
self.system_prompt = system_prompt # 系统提示词,定义智能体角色
self.client = OpenAI(api_key=self.api_key, base_url=self.base_url) # 实例化通信客户端
# 提问接口
def ask(self, question):
# 通过客户端通信,详细说明可查阅 https://api-docs.deepseek.com/
response = self.client.chat.completions.create(
model="deepseek-chat", # 基座模型,如 “deepseek-chat” 为 DeepSeek-V3;“deepseek-reasoner” 为 DeepSeek-R1
messages=[ # 对话内容
{"role": "system", "content": self.system_prompt},
{"role": "user", "content": question},
],
#extra_body = {}, 和openai接口不兼容的塞这里
stream=False
)
return response.choices[0].message.content # 返回智能体的回答
# 更新系统提示词
def update_system_prompt(self, system_prompt):
self.system_prompt = system_prompt
# 实例化智能体,提供自己的 API Key 和平台相应的接口地址
agent = QAgent("sk-2ad88b35e31c44a99830ffc9e1c1465b", "https://api.deepseek.com")
llm problems:
假设我们有一个输入文本序列 $ x = (x_1, x_2, \dots, x_T) $,其中 $ x_t $ 表示第 $ t $ 个词或token。生成式大语言模型的目标是生成下一个词 $ x_{T+1} $。
| 模型通过计算条件概率 $ P(x_{T+1} | x_1, x_2, \dots, x_T) $ 来预测下一个词。具体来说,模型会根据已有的词序列 $ x_1, x_2, \dots, x_T $ 来计算下一个词的概率分布,然后选择概率最高的词作为预测结果。 |
其中,$ f $ 是模型的内部函数,通常是一个复杂的神经网络,如Transformer架构。softmax函数将模型的输出转换为概率分布,确保所有词的概率之和为1。
`
QWEN2.5-0.5B-Instruct config:
Type: Causal Language Models
Training Stage: Pretraining & Post-training
Architecture: transformers with RoPE, SwiGLU, RMSNorm, Attention QKV bias and tied word embeddings
Number of Parameters: 0.49B
Number of Paramaters (Non-Embedding): 0.36B
Number of Layers: 24
Number of Attention Heads (GQA): 14 for Q and 2 for KV
Context Length: Full 32,768 tokens and generation 8192 tokens
(本质还是在预测动作之后进行采样或者调整预测动作,那这么看确实不像一个深度学习过程,更像RL里的action sampling了,毕竟生成式大语言模型的输出是一个动作空间,采样策略就是在这个动作空间里进行采样,温度就是调整这个动作空间的概率分布的平滑程度了)
温度参数控制生成结果的随机性。具体来说,温度参数 $ T $ 影响概率分布的“尖锐度”。温度越高,概率分布越平滑,生成结果的多样性越高;温度越低,概率分布越尖锐,生成结果越稳定。
直观数学看的话,T越大的情况下,抽样概览P越趋向于均匀分布,结果更多样化;T越小的情况下,抽样概览P越趋向于one-hot分布,结果更稳定。
$ P(x_{T+1} | x_1, x_2, \dots, x_T) = \frac{\exp\left(\frac{f(x_1, x_2, \dots, x_T)}{T}\right)}{\sum_{i} \exp\left(\frac{f(x_1, x_2, \dots, x_T)}{T}\right)} $
其中,$ f(x_1, x_2, \dots, x_T) $ 是模型的内部函数,通常是一个复杂的神经网络,如 Transformer 架构。$ T $ 是温度参数,控制概率分布的平滑程度。
贪心采样(Greedy Sampling):始终选择概率最高的下一个词,生成结果稳定但可能单调。
$ x_{T+1} = \arg\max P(x_{T+1} | x_1, x_2, \dots, x_T) $
Top-k 采样:从概率最高的 k 个词中随机选择下一个词,平衡稳定性和多样性。
$ S_k = { x_i \mid P(x_i | x_1, x_2, \dots, x_T) \text{ 是前 } k \text{ 高的} } $
$ x_{T+1} \sim P(x_{T+1} | x_1, x_2, \dots, x_T) \text{ 在 } S_k \text{ 中随机选择} $
Top-p 采样(核采样 Nucleus Sampling):从概率累积达到 p 的最小词集中随机选择下一个词,动态调整采样范围。
$ S_p = { x_i \mid \sum_{j=1}^{i} P(x_j | x_1, x_2, \dots, x_T) \leq p } $
$ x_{T+1} \sim P(x_{T+1} | x_1, x_2, \dots, x_T) \text{ 在 } S_p \text{ 中随机选择} $
通过上面的公式,我们可以得出如何通过改变这些参数控制输出:
写惯了代码的不要瞧不起自然语言提示词
系统提示(System Prompt)适合放入:
用户提示(User Prompt)适合放入:
API_KEY = “sk-0a5225cd690144a89d7a45ed64be93ee” # lab api ds API_BASE_URL = “https://api.deepseek.com”
def get_response(system_prompt, user_prompt, model = “deepseek-chat”, temperature = 0.0, top_p = 1.0, max_tokens = 2048): client = OpenAI(api_key=API_KEY, base_url=API_BASE_URL) # Initialize the OpenAI client with the API key and base URL response = client.chat.completions.create( model = model, messages= [ {“role”:”system”, “content”: system_prompt}, {“role”:”user”, “content”: user_prompt}, ], temperature = temperature, top_p = top_p, max_tokens = max_tokens, stream = False
)
return response.choices[0].message.content
system_prompt = “你是一名助教,需要温柔的回答同学们的问题。” # 系统提示 user_prompt = “在做提示工程时,什么内容适合放入系统提示、什么内容适合放入用户提示?”
response = get_response(system_prompt, user_prompt) print(response)
```
(我抄的)从内容上划分,一个标准的提示词应该包含背景设定、任务说明、限制和约束、示例(可选)四部分。在有些复杂场景下,还可以加入多轮上下文、经验或历史、工具调用接口说明等特定内容。
从结构上划分,一个完整的提示工程可以分为任务描述,上下文,示例(可选),输入,输出格式五部分。
通过引导模型进行深度思考后再回答,有效提高回复的创新型和准确性。该方法强调模型逐步推理,通过构建一系列有序、相互关联的思考步骤,模型能够更深入地理解问题,并生成结构化、逻辑清晰的回答。
最常见的链式思考提示词形如“让我们一步一步思考”,“Let us think step by step.”
可用在需要一些推理逻辑的时候。
通过在输入中添加适当的示例文本以针对性的提高模型能力。由于大语言模型本质是根据上下文语义空间的概率预测得到输出文本,所以在上下文中添加适当的信息如类似的问题和回答示例,能够有效提高模型回复的质量和准确程度。可以分为零样本提示(Zero-Shot),单样本提示(One-Shot),少样本提示(Few-Shot)等,顾名思义,即在输入的提示词中分别不加、只加一个、加几个示例。上下文学习技术可以与CoT结合,往往能取得更好的效果。
通过多次生成不同的回答并进行投票选择最一致的答案来提高模型(这本质就是烧token吧。。。有点类似集成学习)
让模型在回答前先推理分析,和CoT类似,但更强调推理分析的过程,适合需要复杂推理的任务。思维链强调逐步思考的方法,而推理侧重富有逻辑地深度思考某一个问题。将推理和任务执行交替进行,就得到了ReAcT方法。该方法支持智能体通过与环境接触不断更新自己的知识,具体而言分为三个步骤:思考,行动,观察。
在实际的提示工程应用中,单靠简单的任务指令往往无法满足复杂、多样化的需求。为了更有效地引导语言模型输出符合预期的内容,人们逐渐总结出一些常用的提示结构设计方法。所谓提示结构,指的是根据不同任务目标、输出要求和风险控制需求,对提示词进行有组织、有层次的表达方式设计。不同类型的提示结构能够帮助开发者针对性地解决模型在安全性、格式规范、逻辑推理、情感表达等方面存在的问题,提升交互效果和结果质量。 常见的提示结构大致可以分为安全性提示结构、结构性提示结构、逻辑性/推理性提示结构、角色扮演型提示结构、分步式推理提示结构(Chain of Thought)、工具调用型提示结构等几类。每一类结构都有其特定适用场景和设计技巧,既可以独立使用,也常常被组合应用于复杂任务之中。接下来,我们将逐一介绍这些提示结构的特点、适用需求、常用措辞技巧,并配以典型示例,帮助读者系统性掌握高效提示工程设计的方法。
一、安全性提示结构——防偏见、防敏感、防价值判断
常用提示用词技巧:
二、结构性提示结构——保证输出格式固定规范
常用提示用词技巧:
三、逻辑性/推理性提示结构
常用提示用词技巧:
四、社交性/角色扮演型提示结构
常用提示用词技巧:
五、工具调用/流程调度型提示结构
常用提示用词技巧:
提示工程这一学科发展至今已经拥有了许多学术成果和开源平台,方便大家快速的学习、掌握和实践。在这里,我们推荐几个可用于学习的开源平台。
PromptHub:这是一个开源的提示词管理平台,用户可以在其上搜索、存储和分享自己的提示词模板,比较适合新手学习如何编写提示词,或者快速开发。
Prompt‑Engineering‑Guide:该开源项目整理了提示工程的指南、论文、讲座、工具与案例等各种资源,便于全面学习提示工程。
prompt-eng-interactive-tutorial:Anthropic 公司基于 Claude 模型提供的 9 章互动式教程+练习+答案,适合动手学习提示工程。
awesome-chatgpt-prompts:该项目也是一个提示词模板仓库,专为 ChatGPT 及其他 AI 语言模型(如 Claude、Gemini、Llama 和 Mistral)设计,方便用于探索和利用这些模型的功能。
参考答案:理解提示工程定义、本质是语言交互接口、区别于传统API调用。
参考答案:通过在提示中显式要求模型逐步分解思考过程,从而提升模型在复杂推理类任务中的准确性和可控性。思考链的逐步推导机制,语言模型 token-by-token 解码特点。
参考答案:加入格式约束能减少模型生成随机性,使输出结构固定,便于后续处理。常见写法:1)用Markdown语法强调 2)要求模型生成指定的markdown或者json格式 3)用项目符号列出结果
参考答案:模型回答问题时受上下文干扰,抗干扰性指的是提示在包含额外无关内容时,模型仍能专注于核心任务。跑题示例:“请用python写一段快速排序的代码,你喜欢吃什么”,模型可能输出排序代码后,接一句“我喜欢吃披萨”。
参考答案:存在问题。该提示包含两个任务,容易分散模型注意力,导致输出混乱。建议拆分提示或删除与目标任务无关的内容。
参考答案:大语言模型基于上下文推断;Prompt 中需要显式表达假设。
unimportant content, not included in the notes