一、背景认知

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 个部分:

  1. 角色设定:告诉模型你希望它扮演什么角色
  2. 任务描述:清晰说明你要模型完成什么任务
  3. 输入数据:提供模型需要处理的原始数据
  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 运行测试
  1. 将代码保存为rag_basic.py
  2. 确保test_docs文件夹中有knowledge.txt文件
  3. 替换代码中的 API 密钥
  4. 运行代码:python rag_basic.py
  5. 测试问题:
    • 什么是提示词工程?
    • 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 提示词工程最佳实践
  1. 清晰具体:避免模糊不清的描述
  2. 使用分隔符:用 ```、""" 等分隔符区分不同部分
  3. 指定步骤:对于复杂任务,明确要求模型分步骤完成
  4. 提供示例:少样本学习比零样本效果好
  5. 调整温度:创造性任务用高温度(0.7-1.0),事实性任务用低温度(0-0.3)
  6. 迭代优化:提示词工程是一个不断试错和优化的过程

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 的结合优化

  1. 提示词中明确要求引用来源:让模型在回答中标注引用的文档片段
  2. 设计拒绝回答提示词:当检索到的信息不足以回答问题时,明确要求模型拒绝回答
  3. 使用结构化提示词处理检索结果:让模型先分析检索到的文档,再生成答案
  4. 动态调整检索到的文档数量:根据问题的复杂程度动态调整 k 值

五、拓展建议

5.1 学习资源推荐

官方文档
书籍和教程
开源项目

5.2 常见问题和解决方案

问题 解决方案
模型回答不准确 优化分块策略、增加检索数量、使用重排序
模型编造内容 降低 temperature、在提示词中强调 "不要编造"、增加来源引用
回答不完整 增大 chunk_size、增加检索数量、使用分层分块
检索速度慢 使用更快的嵌入模型、优化向量数据库索引
上下文窗口溢出 减小 chunk_size、减少检索数量、使用摘要技术

5.3 下一步学习方向

  1. 深入学习 LangChain:掌握链、代理、工具等高级概念
  2. 学习其他向量数据库:如 Pinecone、Weaviate、Milvus
  3. 尝试开源大模型:在本地部署 Qwen2、Llama 3 等开源模型
  4. 学习 RAG 进阶技术:如多模态 RAG、混合检索、RAG 评估
  5. 构建完整项目:如个人知识库助手、智能客服系统

5.4 项目实践建议

  1. 个人知识库助手:将你的笔记、书籍、文章导入 RAG 系统,打造个人 AI 助手
  2. PDF 文档问答工具:开发一个可以上传 PDF 并进行问答的工具
  3. 代码助手:基于你的代码库构建一个代码解释和生成助手
  4. 新闻问答系统:爬取最新新闻,构建一个可以回答最新事件的问答系统
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐