提示技术系列——生成知识提示
什么是提示技术?
提示技术是实现提示工程目标的具体技术手段,是提示工程中的“工具库”。
什么又是提示工程?
提示工程是指通过设计、优化和迭代输入到大语言模型(LLM)的提示(Prompt),系统性提升模型输出质量(如相关性、准确性、可控性)的实践领域。它是一个覆盖全流程的方法论,包括:
- 明确目标任务(如生成教学内容、问答、翻译);
- 设计提示结构(如指令、上下文、示例);
- 选择模型与参数(如温度、top_p);
- 验证与迭代(根据输出调整提示)。
其核心是“通过工程化方法控制大语言模型(LLM)的行为”。
概念
生成知识提示(Generated Knowledge Prompting),是一种通过分阶段引导模型生成相关知识,再基于知识推理答案的技术。
生成知识提示目的是解决大语言模型的两大短板:
- 知识覆盖不全:模型对专业/常识性知识存在盲区;
-
推理链条断裂:复杂问题缺乏中间知识支撑,导致逻辑跳跃。
工作原理:
首先是知识生成:针对问题生成相关事实或规则;
接着知识整合:将生成的知识与原始问题相结合,引导模型基于新知识推理答案。
概念图解
应用场景
生成知识提示特别适用于以下五类任务:
- 需实时更新知识的任务(金融市场分析、行业预测)
- 高专业门槛任务(法律、医疗)
- 长逻辑链任务(行业报告、教学课程设计)
- 严格一致性任务(合同条款、政策文件)
- 抗幻觉要求高的任务(学术论文、科研综述)
对于严谨的法律、医疗来说,需对生成的知识要进行验证,然后再组合成新的 prompt 使用。
案例实操
演示知识生成提示,使用扣子,可以用工作流来实现。(我之所以不画工作流来演示,是因为没实际需求来画扣子工作流已腻了,想动手写代码,毕竟有 AI Coding 工具,爽。)
大家若是有编程基础的话,可以参考下面的代码案例来实现与体验不同场景下使用知识生成提示。
代码实现知识生成提示
基础案例
技术栈:Python;LangChain
代码相关包引用导入:
pip install langchain_core==0.3.66;
pip install langchain_deepseek==0.1.3;
具体代码实现:
import osfrom dotenv import load_dotenv
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_deepseek import ChatDeepSeek# 加载环境变量
load_dotenv()
api_key = os.getenv("DEEPSEEK_API_KEY")# 初始化模型
llm = ChatDeepSeek(model="deepseek-chat", api_key=api_key, temperature=0.3)# 1. 知识生成阶段
knowledge_prompt = ChatPromptTemplate.from_messages([("system", "针对以下问题生成相关知识,需明确包含规则定义和数据:"),("human", "输入:{question}\n知识:")
])
knowledge_chain = knowledge_prompt | llm# 2. 知识整合阶段
qa_prompt = ChatPromptTemplate.from_messages([("system", "基于以下知识回答问题:\n知识:{knowledge}"),("human", "问题:{question}\n答案:")
])
qa_chain = qa_prompt | llm# 构建完整流程
full_chain = RunnablePassthrough.assign(knowledge=lambda x: knowledge_chain.invoke({"question": x["question"]}).content
) | qa_chain# 测试案例
question = "高尔夫球的一部分是试图获得比其他人更高的得分。是或否?"print("正在处理中,请稍候...")response = full_chain.invoke({"question": question})
print(f"最终答案:{response.content}")
双模型实现案例
技术栈:Python;LangChain
代码相关包引用导入:
pip install langchain_deepseek==0.1.3;
pip install langchain_community==0.3.26;
pip install langchain_core==0.3.66;
具体代码实现:
import osfrom dotenv import load_dotenv
from langchain_community.chat_models import ChatZhipuAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_deepseek import ChatDeepSeek# 加载环境变量
load_dotenv()
api_key_zp = os.getenv("ZHIPUAI_API_KEY")
api_key_ds = os.getenv("DEEPSEEK_API_KEY")# 初始化模型(知识生成与答案整合分离)
zhipu_llm = ChatZhipuAI(model="glm-4", api_key=api_key_zp, temperature=0.7) # 知识生成需更高随机性
ds_llm = ChatDeepSeek(model="deepseek-chat", api_key=api_key_ds, temperature=0.3) # 答案需更稳定# 1. 质谱知识生成提示(强制结构化输出)
ms_knowledge_prompt = ChatPromptTemplate.from_messages([("system", """你是一个质谱分析专家,请生成与问题相关的专业知识,包含以下内容:
1. 原理说明(质谱分析的基本流程)
2. 仪器组成(至少列出3个核心部件)
3. 应用场景(至少2个实际案例)
4. 注意事项(样本处理要求等)输出格式:
```markdown
### 原理
[内容]
### 仪器
- [部件1]: 功能
- [部件2]: 功能
### 应用
- [案例1]: 说明
- [案例2]: 说明
### 注意
[关键注意事项]
```"""),("human", "问题:{question}")
])# 2. 答案整合提示
system_prompt = """你是一个科学问题解答助手,请严格基于以下知识回答问题。
若知识中未包含答案所需信息,必须声明"根据现有知识无法确定"。=== 生成的知识 ===
{knowledge}
==="""
qa_prompt = ChatPromptTemplate.from_messages([("system", system_prompt),("human", "问题:{question}\n答案:")
])# 构建流程(保留中间知识输出)
full_chain = RunnableParallel(knowledge=ms_knowledge_prompt | zhipu_llm,question=RunnablePassthrough() # 保留原始问题
) | {"answer": qa_prompt | ds_llm,"knowledge": lambda x: x["knowledge"].content # 直接提取知识内容}# 测试案例
question = "如何用质谱技术检测食品中的农药残留?需要哪些关键步骤?"
print("正在处理中,请稍候...\n")result = full_chain.invoke({"question": question})# 打印生成的知识
print("===== 生成的专业知识 from GLM-4 model=====")
print(result["knowledge"])
print("\n===== 最终答案 from DeepSeek-chat model =====")
print(result["answer"].content)
使用双模型实现知识生成提示总结:
1. 简单问题:直接使用单模型(qa_chain)避免过度设计(多数场景满足);
2. 专业领域问题:启用双模型但必须添加超时控制与缓存;
3. 高并发场景:采用异步批处理+指数退避策略。
知识生成提示+自我一致性提示
技术栈:Python;LangChain
代码相关包引用导入:
pip install langchain_deepseek==0.1.3;
pip install pydantic==2.11.7;
pip install langchain_core==0.3.66;
具体代码实现:
import os
from collections import Counter
from typing import List, Dictfrom dotenv import load_dotenv
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough, RunnableParallel
from langchain_deepseek import ChatDeepSeek
from pydantic import BaseModel, Field# 1. 环境配置
load_dotenv()
api_key = os.getenv("DEEPSEEK_API_KEY")# 2. 定义数据结构(Pydantic验证)
class KnowledgeItem(BaseModel):method: str = Field(description="解法描述")answer: str = Field(description="数值答案")class GeneratedKnowledge(BaseModel):solutions: List[KnowledgeItem] = Field(description="生成的知识列表")# 3. 初始化模型(结构化输出配置)
llm = ChatDeepSeek(model="deepseek-chat",temperature=0.7,api_key=api_key
).with_structured_output(GeneratedKnowledge) # 关键修改:强制结构化输出# 4. 提示模板设计
knowledge_prompt = ChatPromptTemplate.from_messages([("system", """你是一个数学问题解决专家。请生成3种不同的解法,严格遵循以下JSON格式:
```json
{{"solutions": [[{{"method": "方法1描述", "answer": "纯数字答案"}},{{"method": "方法2描述", "answer": "纯数字答案"}},{{"method": "方法3描述", "answer": "纯数字答案"}}]]
}}"""),("human", "问题:{question}")
])# 5. 构建知识生成链
knowledge_chain = (RunnablePassthrough.assign(question=lambda x: x["question"])| knowledge_prompt| llm
)# 6. 完整流程(含知识输出)
def self_consistency_vote(question: str, num_samples: int = 3) -> Dict:"""执行自我一致性投票"""# 并行生成多组知识results = RunnableParallel(knowledge=lambda x: knowledge_chain.batch([{"question": x["question"]}] * num_samples),question=lambda x: x["question"]).invoke({"question": question})# 展平所有解法all_solutions = []for batch in results["knowledge"]:for solution in batch.solutions:if isinstance(solution, list): # 检查嵌套列表all_solutions.extend(solution)else:all_solutions.append(solution)# 转换为 KnowledgeItem 实例(避免重复实例化)validated_solutions = [solution if isinstance(solution, KnowledgeItem) else KnowledgeItem(**solution)for solution in all_solutions]answers = [sol.answer for sol in validated_solutions] # ['11', '11', '11', '11', '11', '11', '11', '11', '11']final_answer = Counter(answers).most_common(1)confidence = final_answer[0][1] / len(answers)return {"question": question,"knowledge": [sol.model_dump() for sol in validated_solutions], # 输出生成的知识"final_answer": final_answer[0][0] if final_answer else "无法确定","confidence": f"{confidence:.0%}"}# 7. 测试案例
if __name__ == "__main__":# 以下这个水果问题,deepseek-chat 运行了 10次,9错误,置信度100%;1次错误,置信度67%# question = "水果篮子里面有3只苹果,5个香蕉和2个橙子。小红吃了1个香蕉,小明吃了1个苹果,放进了3个橙子。这时水果篮子里一共有多少个水果?"question = "水果篮子里面有3只苹果,5个香蕉和2个橙子。小红吃了1个香蕉,小明吃了1个苹果,放进了3个橙子。这时水果篮子里一共有多少个水果?"print("正在处理中,请稍候...")result = self_consistency_vote(question)# 打印生成的知识print("\n生成的知识:")for i, sol in enumerate(result["knowledge"], 1):print(f"{i}. {sol['method']} → {sol['answer']}")# 打印最终结果print("\n" + "=" * 50)# print(result)print(f"问题: {result['question']}")print(f"最终答案: {result['final_answer']} (置信度: {result['confidence']})")print("=" * 50)
总结与思考
看到,学到这里不知大家是否会有疑问“使用单一大模型下,两次调用同一模型,为啥会使问题得到的结果更加准确,效果更好呢?”
我这么认为的:如果直接让LLM来回答我们的问题(prompt),它给出的答复会存在局部最优解,也就是上一篇文章中提到的“贪婪解码”,模型在每一步解码时只选择当前概率最高的词元(token),并基于该选择继续生成后续内容。
而当第一次生成知识,第二次再调用LLM的时候,给LLM的提示词不只是原来的问题,还有基于问题生成的相关知识,这样就会在一定程度上改进局部最优解带来的影响,从而提高了准确性。
截止到目前为止,我们学习了零样本提示,少样本提示,链式思考提示,自我一致性提示,以及现在的生成知识提示,为了更好地理解它们,对比分析是一个不错的方法。
特性/维度 | 零样本提示 | 少样本提示 | 链式思考提示 | 自我一致性提示 | 知识生成提示 |
是否需要示例 | 不需要 | 需要少量(1~5个) | 需要 CoT 示例 | 需要多个推理路径 | 不一定需要 |
核心机制 | 模型基于任务描述进行泛化推理 | 通过少量示例学习任务模式 | 引导模型输出中间推理步骤 | 多路径推理并选择最一致结果 | 利用已有知识生成新内容 |
适用任务类型 | 简单理解类任务 | 结构化任务(分类、问答等) | 推理类任务(数学题、逻辑题) | 复杂推理任务 | 内容创作、创意任务 |
准确性 | 中低 | 较高 | 高(尤其在复杂任务中) | 更高(优于标准 CoT) | 视提示设计而定 |
资源消耗 | 低 | 中 | 中高 | 高(多次推理) | 中至高 |
优点 | 快速部署、无需数据 | 提升准确率、适应性强 | 支持复杂推理 | 提升推理稳定性与正确率 | 创造力强、个性化程度高 |
缺点 | 复杂任务效果差 | 依赖高质量示例 | 需要特定格式提示 | 成本高、计算量大 | 输出质量不稳定、需审核 |
是不是感觉脑子有一股清流呢?那是脑神经激活的感觉,哈哈……
OK,到此结束。
提示技术系列,接下来分享:链式提示(Prompt Chaining);思维树(ToT);自动提示工程师(APE);主动提示(Active-Prompt);方向性刺激提示等等
为了方便大家学习,这里给出专栏链接:https://blog.csdn.net/quf2zy/category_12995183.html
希望能和大家一起学习与交流……