提示词工程 + RAG 基础 完整入门指南
一、背景认知
1.1 什么是提示词工程?
提示词工程(Prompt Engineering)是一门通过设计和优化输入文本(提示词),来引导大语言模型(LLM)生成高质量、符合预期输出的技术。
核心本质:大模型本质上是 "根据上文预测下一个词" 的概率模型,提示词就是你给模型的 "上文",它决定了模型会从哪个 "知识角落" 和 "思维模式" 来回答你的问题。
为什么重要:
- 无需重新训练模型,就能显著提升输出质量
- 成本极低,效果立竿见影
- 是所有 LLM 应用开发的基础技能
- 能解决模型幻觉、回答不准确、格式混乱等常见问题
1.2 什么是 RAG?
RAG(Retrieval-Augmented Generation,检索增强生成)是一种将外部知识库检索与大模型生成相结合的技术框架。
核心解决的问题:
- ✅ 知识时效性:大模型训练数据有截止日期,无法知道最新信息
- ✅ 私有知识:大模型无法访问企业内部文档、个人笔记等私有数据
- ✅ 幻觉问题:通过引用检索到的真实文档,大幅减少模型编造内容
- ✅ 可解释性:可以追溯答案的来源文档
1.3 提示词工程与 RAG 的关系
- 提示词工程是 RAG 的 "大脑":RAG 检索到的文档片段需要通过精心设计的提示词,才能被模型正确理解和整合
- RAG 是提示词工程的 "延伸":提示词长度有限,RAG 可以将无限多的外部知识 "按需注入" 到提示词中
- 两者相辅相成:好的提示词能让 RAG 效果翻倍,RAG 能让提示词突破上下文窗口限制
1.4 典型应用场景
- 智能客服:基于企业知识库回答客户问题
- 文档问答:对 PDF、Word、网页等文档进行问答
- 代码助手:基于代码库生成和解释代码
- 教育辅导:基于教材生成个性化练习题和解答
- 法律助手:基于法律条文和案例提供咨询
二、核心配置
2.1 环境准备
- Python 版本:3.10 或 3.11(兼容性最好)
- 必备工具:pip(Python 包管理器)、git
- 推荐 IDE:VS Code(安装 Python 和 Jupyter 扩展)
2.2 核心技术栈选择(初学者友好版)
| 组件 | 推荐选择 | 理由 |
|---|---|---|
| 大模型 API | 通义千问 API / 豆包 API | 免费额度高,中文支持好,速度快 |
| 开源大模型 | Qwen2-7B-Instruct | 中文能力强,7B 参数普通电脑可运行 |
| 向量数据库 | Chroma | 纯 Python 实现,无需安装服务,轻量级 |
| 文档处理 | LangChain | 生态最完善,文档加载器丰富 |
| 嵌入模型 | bge-small-zh-v1.5 | 中文效果最好的轻量级嵌入模型 |
2.3 安装依赖包
# 核心依赖
pip install langchain langchain-community langchain-core
pip install chromadb
pip install sentence-transformers
pip install pypdf python-docx
pip install dashscope # 通义千问API
# pip install volcengine-python-sdk # 豆包API
三、基础实操
3.1 第一步:提示词工程基础实践
3.1.1 基础提示词结构
一个好的提示词应该包含以下 4 个部分:
- 角色设定:告诉模型你希望它扮演什么角色
- 任务描述:清晰说明你要模型完成什么任务
- 输入数据:提供模型需要处理的原始数据
- 输出要求:明确输出的格式、长度、风格等
示例:
你是一位专业的Python编程老师,擅长用通俗易懂的语言讲解复杂概念。
请解释下面这段Python代码的功能和工作原理。
输入代码:
def fibonacci(n):
if n <= 1:
return n
else:
return fibonacci(n-1) + fibonacci(n-2)
输出要求:
1. 先说明函数的整体功能
2. 逐行解释代码的执行过程
3. 指出这个实现的优缺点
4. 给出一个更高效的实现版本
3.1.2 思维链(CoT)提示
当遇到复杂的推理问题时,让模型 "一步步思考" 能显著提高准确率。
错误示例:
15个球,拿走3个,又买来4个,现在有多少个?
正确示例(思维链):
15个球,拿走3个,又买来4个,现在有多少个?
请一步步思考并写出计算过程。
3.1.3 结构化输出提示
要求模型输出 JSON、Markdown 等结构化格式,方便后续程序处理。
示例:
请分析下面这段文本的情感倾向,并提取其中的关键信息。
文本:我昨天在XX餐厅吃饭,环境很好,服务也很热情,但是菜的味道一般,价格有点贵。
输出格式:
{
"情感倾向": "正面/负面/中性",
"正面评价": ["评价1", "评价2"],
"负面评价": ["评价1", "评价2"],
"关键信息": ["信息1", "信息2"]
}
3.2 第二步:RAG 基础流程实现
RAG 的完整流程分为索引阶段和查询阶段:
- 索引阶段:文档加载 → 文本分割 → 向量化 → 存储到向量数据库
- 查询阶段:用户问题 → 向量化 → 检索相似文档 → 拼接提示词 → 模型生成答案
3.2.1 准备测试文档
创建一个test_docs文件夹,放入几个测试文档(PDF、Word、TXT 均可)。这里我们先创建一个简单的 TXT 文件knowledge.txt:
提示词工程是一门通过设计和优化输入文本,来引导大语言模型生成高质量输出的技术。
RAG(检索增强生成)是一种将外部知识库检索与大模型生成相结合的技术框架。
LangChain是一个用于构建大语言模型应用的开源框架,提供了丰富的工具和组件。
Chroma是一个轻量级的向量数据库,专为嵌入式AI应用设计。
bge系列嵌入模型是由北京智源人工智能研究院开发的,在中文任务上表现出色。
3.2.2 完整 RAG 代码实现
python
from langchain_community.document_loaders import TextLoader, PyPDFLoader, Docx2txtLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceBgeEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_community.llms import Tongyi
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
import os
# --------------------------
# 配置API密钥(替换为你自己的)
# --------------------------
os.environ["DASHSCOPE_API_KEY"] = "你的通义千问API密钥"
# --------------------------
# 1. 文档加载
# --------------------------
def load_documents(directory_path):
"""加载指定目录下的所有文档"""
documents = []
for filename in os.listdir(directory_path):
file_path = os.path.join(directory_path, filename)
if filename.endswith(".txt"):
loader = TextLoader(file_path, encoding="utf-8")
documents.extend(loader.load())
elif filename.endswith(".pdf"):
loader = PyPDFLoader(file_path)
documents.extend(loader.load())
elif filename.endswith(".docx"):
loader = Docx2txtLoader(file_path)
documents.extend(loader.load())
print(f"成功加载 {len(documents)} 个文档")
return documents
# 加载文档
documents = load_documents("./test_docs")
# --------------------------
# 2. 文本分割
# --------------------------
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每个块的大小(字符数)
chunk_overlap=50, # 块之间的重叠部分
separators=["\n\n", "\n", "。", "!", "?", " ", ""] # 分割优先级
)
splits = text_splitter.split_documents(documents)
print(f"文档被分割为 {len(splits)} 个块")
# --------------------------
# 3. 向量化并存储到向量数据库
# --------------------------
# 加载中文嵌入模型
embeddings = HuggingFaceBgeEmbeddings(
model_name="BAAI/bge-small-zh-v1.5",
model_kwargs={"device": "cpu"}, # 有GPU可以改为"cuda"
encode_kwargs={"normalize_embeddings": True}
)
# 创建向量数据库
vectorstore = Chroma.from_documents(
documents=splits,
embedding=embeddings,
persist_directory="./chroma_db" # 数据库持久化存储路径
)
# 创建检索器
retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索最相似的3个文档
# --------------------------
# 4. 构建RAG链
# --------------------------
# 定义RAG提示词模板
template = """
你是一个专业的知识问答助手。请基于以下提供的上下文信息来回答用户的问题。
如果上下文中没有相关信息,请明确回答"我不知道",不要编造答案。
回答要简洁明了,准确无误。
上下文信息:
{context}
用户问题:{question}
回答:
"""
prompt = ChatPromptTemplate.from_template(template)
# 初始化大模型
llm = Tongyi(model_name="qwen-turbo", temperature=0) # temperature=0表示输出更确定
# 构建RAG链
rag_chain = (
{"context": retriever | (lambda docs: "\n\n".join(doc.page_content for doc in docs)),
"question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
# --------------------------
# 5. 测试问答
# --------------------------
print("RAG系统已准备就绪,输入'退出'结束对话")
while True:
question = input("\n请输入你的问题:")
if question.lower() == "退出":
break
answer = rag_chain.invoke(question)
print(f"回答:{answer}")
3.2.3 运行测试
- 将代码保存为
rag_basic.py - 确保
test_docs文件夹中有knowledge.txt文件 - 替换代码中的 API 密钥
- 运行代码:
python rag_basic.py - 测试问题:
- 什么是提示词工程?
- RAG 是什么意思?
- Chroma 是什么?
- 谁开发了 bge 嵌入模型?
- 今天天气怎么样?(应该回答 "我不知道")
四、高阶用法
4.1 提示词工程进阶
4.1.1 少样本学习(Few-shot Learning)
在提示词中提供几个示例,让模型学习你想要的输出格式和风格。
示例:
请将以下自然语言转换为SQL查询语句。
示例1:
自然语言:查询所有用户的姓名和邮箱
SQL:SELECT name, email FROM users;
示例2:
自然语言:查询年龄大于18岁的用户
SQL:SELECT * FROM users WHERE age > 18;
示例3:
自然语言:查询订单表中总金额超过1000元的订单
SQL:SELECT * FROM orders WHERE total_amount > 1000;
自然语言:查询最近30天注册的用户数量
SQL:
4.1.2 自我一致性(Self-Consistency)
让模型生成多个不同的推理路径,然后投票选择最一致的答案。
示例:
一个商店有12个苹果,卖了5个,又进货了8个,现在有多少个苹果?
请生成3个不同的推理过程和答案,然后选择最合理的一个。
4.1.3 提示词工程最佳实践
- 清晰具体:避免模糊不清的描述
- 使用分隔符:用 ```、""" 等分隔符区分不同部分
- 指定步骤:对于复杂任务,明确要求模型分步骤完成
- 提供示例:少样本学习比零样本效果好
- 调整温度:创造性任务用高温度(0.7-1.0),事实性任务用低温度(0-0.3)
- 迭代优化:提示词工程是一个不断试错和优化的过程
4.2 RAG 进阶技术
4.2.1 分块策略优化
- 语义分块:根据语义而不是字符数来分割文本
- 分层分块:将文档分为大、中、小不同粒度的块
- 元数据增强:为每个块添加标题、页码、作者等元数据
4.2.2 检索重排序(Reranking)
先检索出较多的候选文档(如 20 个),然后用专门的重排序模型对这些文档进行重新排序,选择最相关的几个(如 3 个)传给大模型。
代码示例:
python
from langchain.retrievers import ContextualCompressionRetriever
from langchain_community.document_compressors import FlashrankRerank
# 初始化重排序器
compressor = FlashrankRerank(model="ms-marco-MiniLM-L-12-v2")
# 创建带重排序的检索器
compression_retriever = ContextualCompressionRetriever(
base_compressor=compressor,
base_retriever=vectorstore.as_retriever(search_kwargs={"k": 20})
)
# 使用重排序检索器替换原来的检索器
rag_chain = (
{"context": compression_retriever | (lambda docs: "\n\n".join(doc.page_content for doc in docs)),
"question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
4.2.3 对话式 RAG
支持多轮对话,能够记住上下文信息。
核心改进:在检索之前,先将历史对话和当前问题结合,生成一个独立的问题。
代码示例:
python
from langchain_core.messages import AIMessage, HumanMessage
from langchain_core.prompts import MessagesPlaceholder
# 定义历史对话处理提示词
contextualize_q_system_prompt = """
根据聊天历史和最新的用户问题,将用户问题重述为一个独立的、完整的问题。
不要回答问题,只需要重述问题。
"""
contextualize_q_prompt = ChatPromptTemplate.from_messages([
("system", contextualize_q_system_prompt),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{question}"),
])
# 定义问答提示词
qa_system_prompt = """
你是一个专业的知识问答助手。请基于以下提供的上下文信息来回答用户的问题。
如果上下文中没有相关信息,请明确回答"我不知道",不要编造答案。
回答要简洁明了,准确无误。
上下文信息:
{context}
"""
qa_prompt = ChatPromptTemplate.from_messages([
("system", qa_system_prompt),
MessagesPlaceholder(variable_name="chat_history"),
("human", "{question}"),
])
# 构建历史感知的RAG链
contextualize_q_chain = contextualize_q_prompt | llm | StrOutputParser()
def contextualized_question(input):
if input.get("chat_history"):
return contextualize_q_chain
else:
return input["question"]
rag_chain = (
RunnablePassthrough.assign(
context=contextualized_question | retriever | (lambda docs: "\n\n".join(doc.page_content for doc in docs))
)
| qa_prompt
| llm
| StrOutputParser()
)
# 测试多轮对话
chat_history = []
question1 = "什么是RAG?"
answer1 = rag_chain.invoke({"question": question1, "chat_history": chat_history})
print(f"回答:{answer1}")
chat_history.extend([HumanMessage(content=question1), AIMessage(content=answer1)])
question2 = "它解决了什么问题?"
answer2 = rag_chain.invoke({"question": question2, "chat_history": chat_history})
print(f"回答:{answer2}")
4.3 提示词工程与 RAG 的结合优化
- 提示词中明确要求引用来源:让模型在回答中标注引用的文档片段
- 设计拒绝回答提示词:当检索到的信息不足以回答问题时,明确要求模型拒绝回答
- 使用结构化提示词处理检索结果:让模型先分析检索到的文档,再生成答案
- 动态调整检索到的文档数量:根据问题的复杂程度动态调整 k 值
五、拓展建议
5.1 学习资源推荐
官方文档
书籍和教程
- 《提示词工程:原理与实践》
- 《大语言模型应用开发:基于 LangChain》
- 吴恩达《大语言模型应用开发》课程
- 吴恩达《检索增强生成》课程
开源项目
- LangChain
- Chroma
- llama_index:另一个优秀的 RAG 框架
5.2 常见问题和解决方案
| 问题 | 解决方案 |
|---|---|
| 模型回答不准确 | 优化分块策略、增加检索数量、使用重排序 |
| 模型编造内容 | 降低 temperature、在提示词中强调 "不要编造"、增加来源引用 |
| 回答不完整 | 增大 chunk_size、增加检索数量、使用分层分块 |
| 检索速度慢 | 使用更快的嵌入模型、优化向量数据库索引 |
| 上下文窗口溢出 | 减小 chunk_size、减少检索数量、使用摘要技术 |
5.3 下一步学习方向
- 深入学习 LangChain:掌握链、代理、工具等高级概念
- 学习其他向量数据库:如 Pinecone、Weaviate、Milvus
- 尝试开源大模型:在本地部署 Qwen2、Llama 3 等开源模型
- 学习 RAG 进阶技术:如多模态 RAG、混合检索、RAG 评估
- 构建完整项目:如个人知识库助手、智能客服系统
5.4 项目实践建议
- 个人知识库助手:将你的笔记、书籍、文章导入 RAG 系统,打造个人 AI 助手
- PDF 文档问答工具:开发一个可以上传 PDF 并进行问答的工具
- 代码助手:基于你的代码库构建一个代码解释和生成助手
- 新闻问答系统:爬取最新新闻,构建一个可以回答最新事件的问答系统
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)