LM Studio 本地模型使用指南 / 07 - 提示工程
提示工程
掌握系统提示设计、角色设定和上下文管理技巧,让本地模型发挥最大潜力。
7.1 提示工程概述
什么是提示工程?
提示工程(Prompt Engineering)是设计和优化输入给 LLM 的提示(prompt)的过程,目的是引导模型产生更准确、更有用的输出。
提示工程的核心目标:
糟糕的提示 → 模糊、不相关、冗长的输出
优秀的提示 → 准确、相关、结构化的输出
差距可能非常大,同样的模型:
├── 糟糕提示: "帮我写代码" → 泛泛而谈
└── 优秀提示: "用 Python 写一个 FastAPI 端点..." → 精准可用
提示的组成部分
完整的提示结构:
┌─────────────────────────────────────┐
│ System Prompt(系统提示) │
│ - 角色定义 │
│ - 行为规则 │
│ - 输出格式 │
├─────────────────────────────────────┤
│ Context(上下文) │
│ - 相关背景信息 │
│ - 参考资料 │
│ - 示例数据 │
├─────────────────────────────────────┤
│ User Message(用户消息) │
│ - 具体任务/问题 │
│ - 约束条件 │
│ - 期望输出 │
└─────────────────────────────────────┘
7.2 系统提示设计
系统提示模板
通用模板:
# 角色
你是 [角色描述]。
# 任务
你的任务是 [具体任务描述]。
# 规则
1. [行为规则 1]
2. [行为规则 2]
3. [行为规则 3]
# 输出格式
请以 [格式] 的形式输出。
# 约束
- [约束条件 1]
- [约束条件 2]
设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 明确角色 | 清晰定义 AI 的身份 | “你是一位资深的 Python 开发者” |
| 具体任务 | 明确要做什么 | “审查代码并给出改进建议” |
| 设定边界 | 定义不做什么 | “不要重写整个代码,只指出问题” |
| 指定格式 | 说明输出结构 | “使用 Markdown 表格格式” |
| 提供示例 | 给出期望的输出示例 | “参考以下示例…” |
| 控制长度 | 指定回复长度 | “每个要点不超过 100 字” |
系统提示示例集
示例一:技术顾问
你是一位全栈技术顾问,拥有 15 年的开发经验。
## 专长
- 后端:Python, Go, Node.js
- 前端:React, Vue
- 数据库:PostgreSQL, MongoDB
- 架构:微服务、分布式系统
## 回答规则
1. 先分析问题,再给出方案
2. 提供代码示例时标注语言
3. 推荐技术栈时说明理由
4. 涉及取舍时列出优缺点
## 输出格式
### 问题分析
[分析内容]
### 解决方案
[方案内容]
### 代码示例
[代码]
### 注意事项
[注意事项]
示例二:中文写作助手
你是一位专业的中文技术写作专家。
## 写作规范
- 使用简体中文
- 术语首次出现时附英文,如:大语言模型(LLM)
- 段落之间逻辑连贯,使用过渡句
- 主动语态优先
- 避免口语化表达
## 文档结构
- 使用清晰的标题层级(## / ### / ####)
- 关键信息使用粗体或表格
- 代码块标注语言
- 步骤使用有序列表
## 禁止事项
- 不使用"首先、其次、最后"这种八股文结构
- 不使用"众所周知"等空洞表达
- 不复制粘贴大段概念定义
示例三:SQL 专家
你是一位 PostgreSQL 数据库专家。
## 职责
1. 根据需求编写 SQL 查询
2. 优化慢查询
3. 设计数据库表结构
4. 解释 SQL 执行计划
## 规则
- 使用 PostgreSQL 语法
- 查询要考虑性能(索引、分区)
- 复杂查询添加注释
- 提供 EXPLAIN ANALYZE 结果的解读
## 输出格式
1. 先理解需求
2. 给出 SQL 代码
3. 解释关键部分
4. 提供优化建议(如有)
7.3 角色设定技巧
角色维度
设计角色时考虑的维度:
1. 专业领域
├── 技术栈: Python, Java, Go...
├── 行业: 金融、医疗、电商...
└── 职能: 开发、测试、架构...
2. 经验水平
├── 初级: 基础概念解释
├── 中级: 实践经验分享
└── 高级: 架构设计、最佳实践
3. 沟通风格
├── 严谨: 学术风格,引用来源
├── 实用: 直接给方案,简洁明了
└── 教学: 循序渐进,举例说明
4. 输出偏好
├── 详细: 每个步骤都展开
├── 简洁: 只给关键信息
└── 结构化: 使用表格、列表、代码块
多角色协作
在同一个对话中模拟多角色:
System Prompt:
你是一个产品讨论团队,包含以下角色:
1. PM(产品经理):从用户需求角度分析
2. RD(开发工程师):从技术可行性角度分析
3. QA(测试工程师):从质量保障角度分析
当用户提出需求时,每个角色分别给出意见,
最后给出综合建议。
输出格式:
### PM 视角
[产品分析]
### RD 视角
[技术分析]
### QA 视角
[质量分析]
### 综合建议
[建议]
7.4 提示技巧
技巧一:Few-Shot 学习
通过提供示例来指导模型输出:
System Prompt:
你是一个情感分析工具。根据用户输入判断情感倾向。
示例:
输入: "这家餐厅的菜太好吃了!"
输出: {"sentiment": "positive", "confidence": 0.95}
输入: "服务态度很差,等了一个小时"
输出: {"sentiment": "negative", "confidence": 0.90}
输入: "今天天气还行吧"
输出: {"sentiment": "neutral", "confidence": 0.70}
现在请分析用户输入的情感:
技巧二:思维链(Chain of Thought)
引导模型逐步思考:
System Prompt:
回答问题时,请按以下步骤:
1. 先分析问题的关键信息
2. 列出可能的解决方案
3. 评估每个方案的优缺点
4. 给出最终推荐
请在回复中展示你的思考过程。
技巧三:输出格式控制
明确指定输出格式:
System Prompt:
请以 JSON 格式输出分析结果:
{
"summary": "一句话总结",
"key_points": ["要点1", "要点2"],
"risk_level": "low|medium|high",
"recommendations": ["建议1", "建议2"]
}
只输出 JSON,不要有其他内容。
技巧四:约束边界
设定明确的边界:
System Prompt:
规则:
- 只回答技术问题,拒绝非技术话题
- 如果问题不清楚,要求澄清而不是猜测
- 不确定的内容要标注"不确定"
- 不编造不存在的 API 或库
- 代码示例必须可运行
技巧五:迭代优化
提示优化是一个迭代过程:
第一版:"帮我写个 API"
→ 结果太泛,没有具体信息
第二版:"用 FastAPI 写一个用户注册 API"
→ 有了框架,但缺少细节
第三版:"用 FastAPI 写一个用户注册 API,要求:
- POST /api/users/register
- 字段:username, email, password
- 密码用 bcrypt 加密
- 返回 JWT token
- 包含输入验证"
→ 结果精准可用
7.5 上下文管理
上下文窗口
上下文窗口是模型一次能处理的最大 token 数量:
┌─────────────────────────────────────────┐
│ 上下文窗口 (32K tokens) │
├──────────┬──────────┬──────────┬────────┤
│ System │ 历史消息 │ 当前消息 │ 预留 │
│ Prompt │ │ │ (生成) │
│ ~500 tok │ ~15K tok │ ~5K tok │ ~11K │
└──────────┴──────────┴──────────┴────────┘
当上下文超出限制:
├── 最早的消息会被截断
├── System Prompt 通常优先保留
└── 可能导致模型"遗忘"早期内容
上下文管理策略
"""上下文管理策略示例"""
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:1234/v1",
api_key="lm-studio"
)
class ContextManager:
"""管理对话上下文"""
def __init__(self, max_tokens: int = 32000, reserve_tokens: int = 2000):
self.max_tokens = max_tokens
self.reserve_tokens = reserve_tokens
self.messages: list[dict] = []
self.system_prompt: str | None = None
def set_system_prompt(self, prompt: str):
self.system_prompt = {"role": "system", "content": prompt}
def _estimate_tokens(self) -> int:
"""粗略估算当前 token 数"""
total = 0
for msg in self.messages:
# 粗略估计:1 中文字 ≈ 2 tokens, 1 英文词 ≈ 1.3 tokens
total += len(msg["content"]) * 1.5
return int(total)
def _trim_history(self):
"""当上下文过长时裁剪历史"""
while self._estimate_tokens() > self.max_tokens - self.reserve_tokens:
if len(self.messages) > 2:
# 删除最早的一对消息(user + assistant)
self.messages.pop(0)
if self.messages and self.messages[0]["role"] == "assistant":
self.messages.pop(0)
else:
break
def add_message(self, role: str, content: str):
self.messages.append({"role": role, "content": content})
self._trim_history()
def get_messages(self) -> list[dict]:
msgs = []
if self.system_prompt:
msgs.append(self.system_prompt)
msgs.extend(self.messages)
return msgs
def summarize_and_reset(self) -> str:
"""总结当前对话并重置"""
summary_prompt = "请用 200 字总结我们对话的要点"
response = client.chat.completions.create(
model="qwen2.5-7b-instruct",
messages=self.get_messages() + [
{"role": "user", "content": summary_prompt}
]
)
summary = response.choices[0].message.content
# 重置对话,保留总结
self.messages = [
{"role": "user", "content": f"之前的对话总结:\n{summary}"}
]
return summary
# 使用示例
ctx = ContextManager(max_tokens=8000)
ctx.set_system_prompt("你是一个有帮助的助手")
# 模拟多轮对话
ctx.add_message("user", "什么是微服务?")
ctx.add_message("assistant", "微服务是一种架构风格...")
ctx.add_message("user", "它和单体架构有什么区别?")
ctx.add_message("assistant", "主要区别在于...")
# 当对话过长时,自动总结
if ctx._estimate_tokens() > 6000:
summary = ctx.summarize_and_reset()
print(f"对话已总结:{summary}")
# 获取当前消息
messages = ctx.get_messages()
7.6 常见提示模式
代码生成模式
## 任务
请根据以下需求生成代码:
## 技术栈
- 语言: {language}
- 框架: {framework}
- 版本: {version}
## 需求描述
{requirements}
## 约束
- 代码必须可直接运行
- 包含必要的 import 语句
- 添加关键注释
- 遵循 {style_guide} 代码风格
## 输出格式
```{language}
// 代码
使用说明
// 如何运行和使用
### 数据分析模式
```text
## 角色
你是一位数据分析师。
## 数据
{data_description}
## 分析任务
{analysis_task}
## 输出要求
1. 数据概览(使用表格)
2. 关键发现(使用列表)
3. 可视化建议(使用 Python + matplotlib 代码)
4. 结论和建议
文档翻译模式
## 任务
将以下技术文档从 {source_lang} 翻译为 {target_lang}。
## 翻译规范
- 技术术语保留英文原文,括号注明中文
- 代码块不翻译
- 保持原文的 Markdown 格式
- 保持专业语气
## 原文
{source_text}
7.7 提示调试
常见问题排查
| 问题 | 可能原因 | 解决方案 |
|---|---|---|
| 输出太长 | 没有长度限制 | 添加 “不超过 X 字” |
| 输出格式不对 | 格式要求不明确 | 给出具体示例 |
| 回复"我不知道" | 问题太模糊 | 提供更多上下文 |
| 编造信息 | 模型幻觉 | 要求标注不确定的内容 |
| 忽略指令 | System Prompt 被淹没 | 简化或强调关键指令 |
| 回复不一致 | Temperature 太高 | 降低到 0.3 以下 |
调试流程
提示调试步骤:
1. 明确目标
└── 我期望的输出是什么?
2. 检查系统提示
├── 角色是否明确?
├── 规则是否清晰?
└── 格式是否指定?
3. 检查上下文
├── 是否提供了足够的背景?
└── 是否有干扰信息?
4. 检查用户消息
├── 任务是否明确?
└── 是否有歧义?
5. 调整参数
├── Temperature: 降低以获得更确定的输出
├── Max Tokens: 确保足够生成完整回复
└── Top-P: 调整采样策略
7.8 本章小结
| 要点 | 内容 |
|---|---|
| 系统提示 | 是控制模型行为的最重要手段 |
| 角色设定 | 明确身份、专长、沟通风格 |
| 提示技巧 | Few-Shot、思维链、格式控制、约束边界 |
| 上下文管理 | 注意 token 限制,必要时总结重置 |
| 迭代优化 | 提示设计是一个持续改进的过程 |