有时候,我们只是想利用 LLM 来帮助我们完成一些特定类型的任务,
但每次可能我们跟 LLM 对话的内容只是有一些细微的差别,这时候我们可以使用提示词模板来帮助我们更方便地构建对话。
PromptTemplate
在 langchain
中,我们可以使用 PromptTemplate
来定义一个提示词模板:
from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_openai import ChatOpenAI prompt_template = "What is a good name for a company that makes {product}?" prompt = PromptTemplate(template=prompt_template, input_variables=["product"]) llm = ChatOpenAI( model_name="gpt-3.5-turbo", temperature=0, max_tokens=200, api_key="your key", base_url="https://api.openai-hk.com/v1", ) chain = prompt | llm | StrOutputParser() response = chain.invoke({"product": "shoes"}) print(response)
输出:
SoleStride Footwear Co.
在上面这个例子中,我们的 PromptTemplate
是 What is a good name for a company that makes {product}?
,
在这里,product
是一个变量,我们可以在调用 chain.invoke
的时候传入一个字典,来替换这个变量。
这样,我们就实现了一个模板化的提示词,可以方便地构建对话。
RunnableSerializable
在上面的例子中,chain = prompt | llm | StrOutputParser()
这一行代码我们可能会看得有点懵逼。
这里的 |
并不是常见的 or
运算,而是 prompt
里面的 __or__
方法调用,等于是运算符重载了。
这一行代码的最终结果是,返回一个 RunnableSequence
的实例,我们可以调用它的 invoke
方法。
接着就执行类似管道的操作,前一个操作的输出作为后一个操作的输入。
管道抽象
如果熟悉 linux 命令行的话,我们会知道,其实 linux 中的管道操作符也是 |
。与之类似的,langchain
重载 |
操作符也是为了抽象管道这种操作。
在这行代码中,prompt
的输出会作为 llm
的输入,同时,llm
的输出也会作为 StrOutputParser()
的输入。然后最终得到多个管道处理后的结果。
invoke 实现管道操作的源码
# invoke all steps in sequence try: for i, step in enumerate(self.steps): # mark each step as a child run config = patch_config( config, callbacks=run_manager.get_child(f"seq:step:{i+1}") ) if i == 0: input = step.invoke(input, config, **kwargs) else: input = step.invoke(input, config) # finish the root run except BaseException as e: run_manager.on_chain_error(e) raise
批量调用
我们也可以使用 chain
的 batch
方法来传入多个模板参数:
response = chain.batch([ {"product": "shoes"}, {"product": "cup"}, ])
这样我们就可以同时得到多个问题的答案了。