子任务 1 的输出:"The global temperature has risen by approximately 1.2 degrees Celsius over the past century, with significant increases observed in the past 20 years."
子任务 2 的输入:"Given that global temperatures have risen by 1.2 degrees Celsius over the past century, list the major scientific studies that discuss the causes of these changes."
子任务 2 的输出:"Key studies include: 'The Role of Greenhouse Gases in Global Warming' by Dr. Smith, 'Deforestation and Climate Change' by Dr. Jones, and 'Oceanic Changes and Climate Patterns' by Dr. Lee."
子任务 3 的输入:"Summarize the findings of 'The Role of Greenhouse Gases in Global Warming' by Dr. Smith, 'Deforestation and Climate Change' by Dr. Jones, and 'Oceanic Changes and Climate Patterns' by Dr. Lee, focusing on the impact of climate change on marine ecosystems."
initial_prompt ="Summarize the key trends in global temperature changes over the past century."
follow_up_prompts =["Based on the trends identified, list the major scientific studies that discuss the causes of these changes.","Summarize the findings of the listed studies, focusing on the impact of climate change on marine ecosystems.","Propose three strategies to mitigate the impact of climate change on marine ecosystems based on the summarized findings."]
final_result = prompt_chain(initial_prompt, follow_up_prompts)print("Final result:", final_result)技术支持
defanalyze_sentiment(text):
prompt =f"Analyze the sentiment of the following text and respond with only one word - 'positive', 'negative', or 'neutral': {text}"
sentiment = get_completion(prompt)return sentiment.strip().lower()defconditional_prompt_chain(initial_prompt):
result = get_completion(initial_prompt)if result isNone:return"Initial prompt failed."print(f"Initial output: {result}\n")
sentiment = analyze_sentiment(result)print(f"Sentiment: {sentiment}\n")if sentiment =='positive':
follow_up ="Given this positive outlook, what are three potential opportunities we can explore?"elif sentiment =='negative':
follow_up ="Considering these challenges, what are three possible solutions we can implement?"else:# neutral
follow_up ="Based on this balanced view, what are three key areas we should focus on for a comprehensive approach?"
final_result = get_completion(f"{follow_up}\n\nContext: {result}")return final_result
# Example usage
initial_prompt ="Analyze the current state of renewable energy adoption globally."
final_result = conditional_prompt_chain(initial_prompt)print("Final result:", final_result)技术支持
defcheck_completeness(text):
prompt =f"Analyze the following text and respond with only 'complete' if it covers all necessary aspects, or 'incomplete' if more information is needed:\n\n{text}"
response = get_completion(prompt)return response.strip().lower()=='complete'deflooping_prompt_chain(initial_prompt, max_iterations=5):
current_response = get_completion(initial_prompt)if current_response isNone:return"Initial prompt failed."print(f"Initial output: {current_response}\n")
iteration =0while iteration < max_iterations:if check_completeness(current_response):print(f"Complete response achieved after {iteration +1} iterations.")return current_response
print(f"Iteration {iteration +1}: Response incomplete. Expanding...")
expand_prompt =f"The following response is incomplete. Please expand on it to make it more comprehensive:\n\n{current_response}"
new_response = get_completion(expand_prompt)if new_response isNone:returnf"Expansion failed at iteration {iteration +1}."
current_response = new_response
print(f"Expanded response: {current_response}\n")
iteration +=1print(f"Maximum iterations ({max_iterations}) reached without achieving completeness.")return current_response
# Example usage
initial_prompt ="Explain the process of photosynthesis."
final_result = looping_prompt_chain(initial_prompt)print("Final result:", final_result)技术支持
defsplit_document(document, max_length=1000):"""Split the document into sections of approximately max_length characters."""
words = document.split()
sections =[]
current_section =[]
current_length =0for word in words:if current_length +len(word)+1> max_length and current_section:
sections.append(' '.join(current_section))
current_section =[]
current_length =0
current_section.append(word)
current_length +=len(word)+1if current_section:
sections.append(' '.join(current_section))return sections
defsummarize_section(section):
prompt =f"Summarize the following text in a concise manner:\n\n{section}"return get_completion(prompt)defanswer_question(summaries, question):
context ="\n\n".join(summaries)
prompt =f"Given the following context, answer the question:\n\nContext:\n{context}\n\nQuestion: {question}"return get_completion(prompt)defdocument_qa(document, questions):# Step 1: Split the document
sections = split_document(document)print(f"Document split into {len(sections)} sections.")# Step 2: Summarize each section
summaries =[]for i, section inenumerate(sections):
summary = summarize_section(section)
summaries.append(summary)print(f"Section {i+1} summarized.")# Step 3: Answer questions
answers =[]for question in questions:
answer = answer_question(summaries, question)
answers.append((question, answer))return answers
# Example usage
long_document ="""
[Insert a long document here. For brevity, we are using a placeholder.
In a real scenario, this would be a much longer text, maybe several
paragraphs or pages about a specific topic.]
This is a long document about climate change. It discusses various aspects
including causes, effects, and potential solutions. The document covers
topics such as greenhouse gas emissions, rising global temperatures,
melting ice caps, sea level rise, extreme weather events, impact on
biodiversity, and strategies for mitigation and adaptation.
The document also explores the economic implications of climate change,
international agreements like the Paris Agreement, renewable energy
technologies, and the role of individual actions in combating climate change.
[Continue with more detailed information about climate change...]
"""
questions =["What are the main causes of climate change mentioned in the document?","What are some of the effects of climate change discussed?","What solutions or strategies are proposed to address climate change?"]
results = document_qa(long_document, questions)for question, answer in results:print(f"\nQ: {question}")print(f"A: {answer}")技术支持
defgenerate_text(topic):
prompt =f"Write a short paragraph about {topic}."return get_completion(prompt)defextract_facts(text):
prompt =f"Extract the key factual claims from the following text, listing each claim on a new line:\n\n{text}"return get_completion(prompt)defverify_facts(facts):
verified_facts =[]for fact in facts.split('\n'):if fact.strip():
prompt =f"Verify the following statement and respond with 'True' if it's factually correct, 'False' if it's incorrect, or 'Uncertain' if it can't be verified without additional research: '{fact}'"
verification = get_completion(prompt)
verified_facts.append((fact, verification.strip()))return verified_facts
defrevise_text(original_text, verified_facts):
context ="Original text:\n"+ original_text +"\n\nVerified facts:\n"for fact, verification in verified_facts:
context +=f"- {fact}: {verification}\n"
prompt =f"{context}\n\nRewrite the original text, keeping the verified facts, removing or correcting any false information, and indicating any uncertain claims as 'It is claimed that...' or similar phrasing."return get_completion(prompt)deftext_generation_with_verification(topic):print(f"Generating text about: {topic}")# Step 1: Generate initial text
initial_text = generate_text(topic)print("\nInitial Text:")print(initial_text)# Step 2: Extract facts
extracted_facts = extract_facts(initial_text)print("\nExtracted Facts:")print(extracted_facts)# Step 3: Verify facts
verified_facts = verify_facts(extracted_facts)print("\nVerified Facts:")for fact, verification in verified_facts:print(f"- {fact}: {verification}")# Step 4: Revise text
revised_text = revise_text(initial_text, verified_facts)print("\nRevised Text:")print(revised_text)return revised_text
# Example usage
topic ="the effects of climate change on polar bears"
final_text = text_generation_with_verification(topic)技术支持
defgenerate_code(task):
prompt =f"Write a Python function to {task}. Include comments explaining the code."return get_completion(prompt)defgenerate_test_cases(code):
prompt =f"Given the following Python code, generate 3 test cases to verify its functionality. Include both input and expected output for each test case:\n\n{code}"return get_completion(prompt)defrun_tests(code, test_cases):
prompt =f"""
Given the following Python code and test cases, run the tests and report the results.
If any tests fail, explain why and suggest fixes.
Code:
{code}
Test Cases:
{test_cases}
For each test case, respond with:
1. "PASS" if the test passes
2. "FAIL" if the test fails, along with an explanation of why it failed and a suggested fix
"""return get_completion(prompt)defdebug_code(code, test_results):
prompt =f"""
Given the following Python code and test results, debug the code to fix any issues.
Provide the corrected code along with explanations of the changes made.
Original Code:
{code}
Test Results:
{test_results}
"""return get_completion(prompt)defcode_generation_with_debugging(task):print(f"Generating code for task: {task}")# Step 1: Generate initial code
initial_code = generate_code(task)print("\nInitial Code:")print(initial_code)# Step 2: Generate test cases
test_cases = generate_test_cases(initial_code)print("\nGenerated Test Cases:")print(test_cases)# Step 3: Run tests
test_results = run_tests(initial_code, test_cases)print("\nTest Results:")print(test_results)# Step 4: Debug code if necessaryif"FAIL"in test_results:print("\nDebugging code...")
debugged_code = debug_code(initial_code, test_results)print("\nDebugged Code:")print(debugged_code)# Optionally, you can run tests again on the debugged codeprint("\nRe-running tests on debugged code...")
final_test_results = run_tests(debugged_code, test_cases)print("\nFinal Test Results:")print(final_test_results)return debugged_code
else:print("\nAll tests passed. No debugging necessary.")return initial_code
# Example usage
task ="calculate the factorial of a number"
final_code = code_generation_with_debugging(task)技术支持
defsolve_step_by_step(problem):
steps =[]
current_problem = problem
whileTrue:
prompt =f"Solve the following problem step by step. Provide the next step only and explain it clearly:\n\n{current_problem}"
step = get_completion(prompt)if step isNoneor"solution"in step.lower():break
steps.append(step)
current_problem =f"{current_problem}\n\n{step}"print(f"Step {len(steps)}: {step}\n")return steps
defcombine_steps(steps):
combined_steps ="\n".join(steps)
prompt =f"Combine the following steps into a coherent solution for the problem:\n\n{combined_steps}"return get_completion(prompt)defmulti_step_reasoning(problem):print(f"Solving problem: {problem}")# Step 1: Solve step by step
steps = solve_step_by_step(problem)# Step 2: Combine steps into a final solution
final_solution = combine_steps(steps)print("\nFinal Solution:")print(final_solution)return final_solution
# Example usage
problem ="A car travels 60 miles per hour for 2 hours, then 40 miles per hour for 3 hours. What is the total distance traveled by the car?"
final_solution = multi_step_reasoning(problem)技术支持
首先,solve_step_by_step() 将问题拆分为更小的部分,逐步向模型请求下一步,直至完成解答,并保存每一步。随后 combine_steps() 汇总所有步骤,请模型将其合并为一段清晰的解释。整个过程中由 get_completion() 负责与 OpenAI API 交互。
不妨替换掉:“Can you please summarize the key points of the historical trends in global temperatures over the past century, focusing on any significant changes and their potential causes, as well as notable events that might have influenced these trends?”
为:“Summarize the key points of historical global temperature trends over the past century.”
Ana Rojo Echeburúa 是一位人工智能与数据专家,拥有应用数学博士学位。她热衷于将数据转化为可执行的洞见,并在带领技术团队方面拥有丰富经验。Ana 喜欢与客户密切合作,解决其业务难题并打造创新的 AI 解决方案。她以出色的问题解决能力和清晰的沟通著称,对人工智能,尤其是生成式 AI 充满热情。Ana 致力于持续学习与负责任的 AI 开发,同时专注于简化复杂问题,并以通俗易懂的方式解释技术。
您有没有在不看说明书的情况下组装过家具?运气好时,可能能装上几块,但没有一步步的指引,结果往往一团糟。大语言模型(LLM)在处理复杂问题时也会面临类似的挑战。它们潜力巨大,但当任务需要细致的多步推理时,常常难以命中要点。
只给一个提示时,LLM 可能会给出过于宽泛、缺乏深度或遗漏关键细节的答案。这是因为很难在单一提示中捕捉全部必要背景并提供足够的引导。
解决方法就是提示链。
提示链是将复杂任务拆解为一系列更小、更易管理的提示。每个提示解决任务的一个特定部分,一个提示的输出作为下一个提示的输入。该方法提供更有结构的路径,引导 LLM 通过一连串推理步骤,得到更准确、全面的答案。通过一组逻辑有序的提示,我们可以充分发挥 LLM 的能力,高效解决复杂问题。
本教程属于我的“提示工程:从入门到精通”系列博文:
什么是提示链?
提示链是指在一个序列中,将某个 LLM 提示的输出作为下一个提示的输入。这一技术会创建一系列相互衔接的提示,每个提示聚焦于整体问题的某个部分。遵循这一序列可以引导 LLM 进行结构化推理,帮助其生成更准确、更细致的响应。
提示链的主要目的在于提升 LLM 应用的性能、可靠性与清晰度。对于复杂任务,单一提示往往无法提供足够的深度和背景,从而难以获得理想答案。提示链通过把任务拆分为更小的步骤,并确保每一步都得到妥善处理来解决这一问题。该方法既提升了 LLM 输出质量,也更便于理解最终结果是如何达成的。
来看一下提示链的一些好处:
优势
描述
示例
拆解复杂性
将复杂任务分解为更小、可管理的子任务,使 LLM 能一次专注于一个方面。
逐步生成一篇研究论文(大纲、章节、结论),而不是一次性完成。
提升准确性
通过中间步骤引导 LLM 的推理,提供更多上下文,从而得到更精确、相关的回答。
诊断技术问题:先识别症状,再收敛原因,最后给出解决方案。
增强可解释性
提高 LLM 决策过程的透明度,更易理解其结论是如何得出的。
解释法律裁决:先列出相关法律,再将其应用于案例,最后给出结论,并清晰记录每一步。
如何实现提示链
实现提示链需要系统性地拆解复杂任务,并引导 LLM 按照一系列明确步骤完成。
下面看看如何有效创建并执行一个提示链。
识别子任务
第一步是将复杂任务分解为更小、可管理的子任务。每个子任务都应代表整体问题的一个独立方面。这样 LLM 就能一次专注于一个部分。
例如,若希望 LLM 撰写一份关于气候变化的综合报告,子任务可以包括:
设计提示
接下来,为每个子任务设计清晰、简洁的提示。每条提示都应具体、直接,确保 LLM 理解任务并能生成相关输出。重要的是,一个提示的输出应能自然作为下一个提示的输入,形成信息流。
针对上述子任务,可以这样设计提示:
链式执行
现在按顺序执行这些提示,将上一步的输出作为下一步的输入。逐步执行能确保 LLM 在此前输出的基础上构建,形成连贯而完整的结果。
在我们的示例中,子任务的输出可能如下:
错误处理
实现错误处理机制对于应对提示执行过程中可能出现的问题至关重要。这可以包括在进入下一步前设置检查,验证输出的质量与相关性;以及创建回退提示,使 LLM 在偏离预期路径时重回正轨。例如:
实现
下面看看如何用 Python 实现!
步骤 1:设置环境
首先需要导入必要的库。我们将使用
openai包中的OpenAI类,以及用于处理环境变量的os。安全存储敏感信息(如 API 密钥)至关重要。将 API 密钥设置为环境变量是一种可行方式。您可以使用OpenAI API 密钥来完成。
请将
'your-api-key-here'替换为您实际的 OpenAI API 密钥。设置好 API 密钥后,您可以初始化 OpenAI 客户端。此客户端用于向 OpenAI 服务发起 API 调用。
步骤 2:定义与 OpenAI 聊天补全 API 交互的函数
现在,我们创建一个 Python 函数与 OpenAI 的聊天补全 API 交互。该函数会向 API 发送提示并返回生成的响应。
我们来分解一下该函数——它:
None。步骤 3:串联多个提示
现在我们创建一个 Python 函数,将多个提示串联起来,把上一步的输出作为下一步的输入。
prompt_chain函数实现了提示链。它:步骤 4:示例用法
我们将演示如何使用
prompt_chain创建一组相互构建的提示。此示例聚焦于概括全球气温变化趋势,并探索相关科学研究与减缓策略,您也可应用到自己的用例中!这里我们先定义一个关于全球气温变化的初始提示,然后设置一组逐步推进的后续提示。接着用这些提示调用
prompt_chain函数,最后打印最终结果。如何协同工作
我们来总结一下流程:
这种链式方式可逐步处理复杂问题,每一步都建立在前面步骤的信息之上。
提示链技术
提示链可根据不同任务与需求以多种方式实现。这里介绍三种主要技术:顺序链、条件链与循环链。
顺序链(Sequential chaining)
顺序链以简单、线性的方式连接提示。每个提示依赖于前一个提示的输出,形成按部就班的信息与任务流。该技术非常适合需要从一个阶段逻辑推进到下一个阶段的任务,例如:
上一节的代码片段就是顺序链的示例。
条件链(Conditional chaining)
条件链根据 LLM 的输出在提示链中引入分支。该技术能创建更灵活、可适应的工作流,让 LLM 根据生成的响应走不同路径。
下面看看如何用条件链进行情感分析。
首先我们定义新函数
analyze_sentiment(),用语言模型判断给定文本的情感。接着在conditional_prompt_chain()中,从关于可再生能源采纳现状的初始提示开始。拿到初步响应后,我们进行情感分析,并据此选择不同的后续提示:然后将选定的后续提示与初始响应的上下文一起发送给语言模型,最终结果即为对此条件后续提示的回答。
注意第二个提示的选择不是预先固定的,而是取决于第一次响应的内容;对话流程也会基于情感分析而自适应,展示了链路如何分叉。这让与语言模型的交互更具动态性与上下文感知。
运行这段代码时,具体的后续问题会取决于最初对可再生能源采纳状况的分析被判定为正面、负面还是中性,从而形成更具适应性与响应性的提示链。
循环链(Looping chaining)
循环链是在提示链中创建循环,以便对数据进行迭代或执行重复性任务。该技术适用于需要对多个条目按相似步骤处理的场景。其优劣点包括:
以下示例展示了如何将循环链用于文本完整性任务:
首先定义新函数
check_completeness(),用语言模型判断给定响应是否完整,或是否需要更多信息。然后在
looping_prompt_chain()中,从关于光合作用的初始提示开始。得到初次响应后进入循环:这一过程会持续,直到得到被判定为完整的响应,或达到最大迭代次数(默认 5 次)。
循环确保不断细化和扩展响应,直到其被视为完整,或达到迭代上限。
运行这段代码时,它会尝试给出关于光合作用的全面解释;如果初始响应不够完整,可能会进行多次扩展迭代,从而产生更全面、可自适应的提示链并得到尽可能完善的最终结果。
提示链的实践应用
提示链可显著增强 LLM 在多种应用中的能力。本节将探讨一些实际用法,展示其如何落地到真实任务。
基于文档的问答
提示链可用于先摘要长文档,再回答具体问题。流程是先将文档拆分为易管理的部分,对每部分进行摘要,再用这些摘要回答细化问题。
实现如下:
这段代码展示了如何用提示链处理文档分析与问答等复杂任务。它将“理解长文档”的大任务拆分为“分段摘要”等更小的步骤,并将一步的输出(摘要)作为下一步(答题)的输入,从而处理那些无法在单个提示中直接完成的长文档。
当您用真实的长文档运行这段代码时,它会将文档拆分为易管理的部分,对每部分进行摘要,并据此回答关于气候变化成因、影响与解决方案的问题。
带事实校验的文本生成
带事实校验的文本生成是在提示链中加入事实核查步骤,确保输出既连贯又准确。
text_generation_with_verification()函数统筹整个流程。它先用generate_text()生成主题段落,再由extract_facts()提取关键论断,verify_facts()对这些论断进行核验(标注为 True、False 或 Uncertain),最后revise_text()基于核验结果重写原文,修正错误并标明不确定信息,确保最终文本既信息量充足又更为准确。提示链体现在多个环节:先生成文本,再从中抽取事实、逐条核验,并据此修订文本。
当以“气候变化对北极熊的影响”为主题运行时,它会先生成初始文本,再抽取并核验事实,最后基于核验结果修订文本,得到更准确的输出。您也可以换成自己感兴趣的主题!
带调试的代码生成
利用提示链先写代码再测试,可以加快开发节奏。这种方法有助于确保代码不仅能运行,而且能按预期工作,超越了仅仅“无错误运行”的层面。
code_generation_with_debugging()函数统筹整个过程:首先generate_code()为任务生成 Python 代码;接着generate_test_cases()创建测试用例;然后run_tests()检查代码是否通过测试;若有失败,debug_code()负责定位并修复问题。请注意,每一步都建立在前一步的基础上:先写代码,再生成测试、运行测试并修复问题。这样把编码流程拆解为更小、更易处理的步骤,展示了提示链如何应对编码等复杂任务,模拟真实开发流程:写代码、测试、修复。每一步都利用之前的成果,推动代码逐步完善。
当以“计算一个数的阶乘”为任务运行时,它会生成初始实现、创建测试用例、模拟运行并报告结果;若有失败,将尝试调试修复,并再次运行测试。
多步推理任务
提示链可用于解决需要多步推理的复杂问题,如数学应用题或逻辑谜题。每一步都建立在上一步之上,确保过程结构化且充分。
首先,
solve_step_by_step()将问题拆分为更小的部分,逐步向模型请求下一步,直至完成解答,并保存每一步。随后combine_steps()汇总所有步骤,请模型将其合并为一段清晰的解释。整个过程中由get_completion()负责与 OpenAI API 交互。本示例将求解这样的问题:“一辆车以每小时 60 英里行驶 2 小时,然后以每小时 40 英里行驶 3 小时。这辆车总共行驶了多远?”
运行后,代码会把问题拆成更小的推理步骤,收集并打印每一步,再将这些步骤合并为最终解答并打印出来。
提示链最佳实践
为了最大化提示链的效果,遵循若干最佳实践非常关键。这些做法能让链路更健壮、准确和高效,从而带来更好的结果与更可靠的 LLM 应用。
提示设计
清晰、简洁的提示对于获得理想结果至关重要。提示越直白,模型越容易理解您的需求,从而降低歧义并提升回答质量。
一些建议:
例如:
结构良好的提示也有助于 LLM 按照任务的逻辑顺序推进。组织有序、连贯的提示能让模型更好地理解并做出恰当回应。
一些建议:
以这种方式构建提示,可引导 LLM 按步骤完成任务,得到更好更准确的回应。例如:
实验探索
不同任务需要不同的链式方法。为任务选对方法至关重要。建议多尝试不同思路,比较效果,从而找到最适合您目标的方案。
同时应定期评估提示链的表现,关注输出的准确性、完整性与相关性。这样能识别优缺点,便于持续改进,确保获得最佳结果。
迭代优化
基于反馈与结果进行迭代优化,有助于得到更精准有效的提示。通过收集输出反馈、识别不足并相应调整提示,您可以持续提升 LLM 的表现。这一持续过程能让提示随着时间推移愈发准确、相关。例如:
优化链路结构
提示链的组织方式会直接影响结果。根据实际效果调整提示的顺序与逻辑,确保每一步都能顺畅衔接,从而获得更合理的回答。
错误处理
健壮的错误处理可在个别提示失败时,仍维持提示链的整体运行。通过设置输出有效性检查与回退提示,您可以在出现错误时引导 LLM 回到正轨,保持链路的连贯性与可靠性,确保一致的表现。
监控与日志
持续监控提示链的表现很重要,这有助于了解有效之处并发现问题。使用工具记录关键信息,如提示的输入与输出、耗时等。例如,记录链路的每一步、各自产出以及发生的错误。这样便于分析流程并改进,提升结果质量。
详尽的记录有助于排错并优化提示链。请妥善整理这些记录,便于复盘与学习,从而发现问题并微调链路,使其运行更佳、答案更准确。
遵循上述最佳实践,您将能够创建高效且可靠的提示链,提升 LLM 的能力,在多种应用中获得更好的性能与更有意义的结果。
结语
本文介绍了提示链,这是一种通过将复杂任务拆解为更小的提示来增强 LLM 在复杂场景下表现的技术。我们涵盖了不同的链式方法、应用场景与最佳实践,帮助您在广泛用例中高效利用 LLM。
如果您想进一步学习提示工程,推荐阅读以下文章: