第7章ChatGPT Prompting开发实战
Prompting在LangChain框架中的应用
本节跟大家讲提示工程(Prompt Engineering),主要基于工业级的源码以及具体的项目,无论是工程人员,还是不具有技术背景的人员,大家多少都听说过提示词,或者频繁使用过,简单而言,当我们使用OpenAI的时候,使用它的API或者ChatGPT,使用提示词跟它进行沟通,如图7-1所示,这是ChatGPT的界面,作者一般使用GPT-4大模型。
图7- 1 ChatGPT界面
你在这里面输入的任何信息,从模型的角度讲都叫提示词(Prompt),但工业级的提示词和通常大家理解中的提示词不太一样,我们首先来看一下,工业级的提示词是什么样,给大家准备了很多具体的例子,如图7-2所示,这些例子基本都来自于DeepLearning.AI,从提示词的角度,这些例子是非常系统化的,而且非常有价值,例如,这边谈到的思维链(chains-of-thought),显然是一个非常重要的例子。Gavin大咖微信:NLP_Matrix_Space
图7- 2 提示词案例
现在开源界、工业界和学术界认可度最高的大模型应用开发框架是LangChain,它涉及大量提示词的使用,这里面的提示词经过很多人的评审以及改进,还有工业界的实践,或者学术研究的实践。如果下载LangChain的源码,你会发现LangChain在不同的功能下面,基本上都会有提示词(Prompt),如图7-3所示。
图7- 3 LangChain功能目录
举一个简单的例子,任意看一个目录,例如retrieval_qa,base.py可以认为是一个基本的API,然后核心部分是它的提示词(prompt),如图7-4所示。
图7- 4 retrieval_qa的提示词
prompt.py中的提示词会有一个模板(template),描述为“Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.”(“使用以下上下文来回答问题。如果你不知道答案,就说你不知道,不要试图编造答案。”)
prompt.py的代码实现:
# flake8: noqa
from langchain.prompts import PromptTemplate
prompt_template = """Use the following pieces of context to answer the question at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.
{context}
Question: {question}
Helpful Answer:"""
PROMPT = PromptTemplate(
template=prompt_template, input_variables=["context", "question"]
可以再看一下示例,例如:question_answering,它提供map_reduce_prompt、map_rerank_prompt、refine_prompts、stuff_prompt等提示模板的信息。
图7- 5 question_answering的提示词
map_reduce_prompt.py代码设置了一个自己特定格式的问题提示模板,描述为:“Use the following portion of a long document to see if any of the text is relevant to answer the question. Return any relevant text verbatim”(“使用长文档的以下部分,查看是否有任何文本与回答问题相关,逐字返回任何相关文本”),这边有上下文(context),有问题(question)和相关的内容。
map_reduce_prompt.py的代码实现:
…
question_prompt_template = """Use the following portion of a long document to see if any of the text is relevant to answer the question.
Return any relevant text verbatim.
{context}
Question: {question}
Relevant text, if any:"""
QUESTION_PROMPT = PromptTemplate(
template=question_prompt_template, input_variables=["context", "question"]
)
system_template = """Use the following portion of a long document to see if any of the text is relevant to answer the question.
Return any relevant text verbatim.
______________________
{context}"""
messages = [
SystemMessagePromptTemplate.from_template(system_template),
HumanMessagePromptTemplate.from_template("{question}"),
]
CHAT_QUESTION_PROMPT = ChatPromptTemplate.from_messages(messages)
…….
也可以看一下query_constructor,如图7-6所示。
图7- 6 query_constructor的提示词
在prompt.py代码文件中,也给了很多关于提示词信息,包括它的一些描述。
prompt.py的代码实现:
….
EXAMPLES_WITH_LIMIT = [
{
"i": 1,
"data_source": SONG_DATA_SOURCE,
"user_query": "What are songs by Taylor Swift or Katy Perry about teenage romance under 3 minutes long in the dance pop genre",
"structured_request": FULL_ANSWER,
},
{
"i": 2,
"data_source": SONG_DATA_SOURCE,
"user_query": "What are songs that were not published on Spotify",
"structured_request": NO_FILTER_ANSWER,
},
{
"i": 3,
"data_source": SONG_DATA_SOURCE,
"user_query": "What are three songs about love",
"structured_request": WITH_LIMIT_ANSWER,
},
]
EXAMPLE_PROMPT_TEMPLATE = """\
<< Example {i}. >>
Data Source:
{data_source}
User Query:
{user_query}
Structured Request:
{structured_request}
"""
EXAMPLE_PROMPT = PromptTemplate(
input_variables=["i", "data_source", "user_query", "structured_request"],
template=EXAMPLE_PROMPT_TEMPLATE,
)
….
不过,我们在这一节看的重点是代理(Agents),如图7-7所示,代理有很多不同的种类,有两个特别重要,大家必须注意的,一个是react,另外一个叫mrkl。Gavin大咖微信:NLP_Matrix_Space
图7- 7 LangChain的Agent目录
如果你做工业级强度、基于大模型的应用开发,一般都要有一个管理者,可以统称为代理(Agent),我们谈ChatGPT插件(Plugin)的时候,其实就是从代理的角度去考虑事情,是代理的思路。gpt-4-0613和gpt-3.5-turbo-0613是OpenAI公司在2023年6月新发布的模型,它可以很好的支持函数调用(Function calling),OpenAI官网的文档中说了一句非常关键的话:大模型从你的信息中提取出函数的名称、函数的参数,传递给你去调动函数,大模型本身并不会直接去调动函数,因为你是直接运行在模型上面,并没有一个服务(server)。回到LangChain,LangChain其实包含了上面所有的功能,包括ChatGPT插件的功能,包括OpenAI函数调用(Function calling)的功能,OpenAI提供的功能,可以立即映射到LangChain上面。所以,这边的核心问题是让它有效的工作,而不是你简单的输入信息,然后你获得这个结果,当然这个结果可能包含一些步骤、或者一些互动等等。但是,如果你没有代理的话,你只能是生成文本,无法执行动作(Action),而如果你开发一个应用程序,肯定要实现Action,这是代理(Agent)的主要作用。从开源软件命名的角度讲,LangChain最开始的时候,核心聚焦的是Chain,后来聚焦Agent。
如图7-8所示,是mrkl代理的目录结构,“MRKL Systems”论文的作者把它的发音作为ˈmɪrək(ə)l,和奇迹(miracle)的发音相同。
图7- 8 mrkl的目录结构
如图7-9所示,MRKL(Modular Reasoning,Knowledge and Language)是一种新型语言理解系统,将神经网络模型、外部知识库和专家系统相结合,兼顾神经模型和符号推理能力,提升了自然语言处理的效率。
图7- 9 MRKL架构示意图