LangChain补充一:一些小且有用的点
一:LangChain 表达式语言LCEL(LangChain Expression Language)
chain:我们可以将包括大模型调用在内的一组操作组成“链条”,即所谓“调用链”
(一)概念
LangChain 提供的 LangChain Expression Language(LCEL) 让开发可以很方便地将多个组件连接成 AI 工作流(或者说是调用链)。如下是一个简单的工作流:
chain = prompt | chatmodel | outputparser chain.invoke({"input":"What's your name?")
其中,通过由
|
管道操作符连接而成的 LangChain 表达式,我们方便地将三个组件 prompt
chatmodel
outparser
按顺序连接起来,这就形成了一个 AI 工作流。 invoke()
则是实际运行这个工作流。我们还可以组织较为复杂的 AI 工作流,如下所示,其中进行两次模型调用,并且示例中用的两个不同的模型。
chain = ( prompt | chatmodel | outputparser | second_prompt | model2 | finalparser ) chain.invoke("input":"waht's AI?")
(二):通过LCEL实现多次调用模型
多次调用模型,分步来进行操作,从而利用模型的能力得到更符合期待的结果。
from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser from langchain_core.runnables import RunnablePassthrough from IPython.display import Markdown llm = ChatOpenAI( model_name="gpt-4-1106-preview" #创建聊天模型示例。这里采用 gpt-4-1106-preview 模型 ) prompt = ChatPromptTemplate.from_messages([ ("system", "You are world class technical documentation writer."), ("user", "{input}") ]) #创建第一次模型调用的提示语模板。其中系统提示语是“You are world class technical documentation writer.”(你是一个世界级的技术文档编写者。) translate_prompt = ChatPromptTemplate.from_messages([ ("system", "Translate to simplified Chinese."), ("user", "{input}") ]) #创建第二次模型调用的提示语模板。其中系统提示语是“Translate to simplified Chinese.”(翻译为简体中文。) output_parser = StrOutputParser() #StrOutputParser,它可将输出解析为易读的文本格式,将 AIMessage 转换成 string chain = prompt | llm | output_parser \ | {"input": RunnablePassthrough()} \ | translate_prompt | llm | output_parser #建立调用链。其中用 RunnablePassthrough() 将第一次模型的输出作为第二次的输入。 output = chain.invoke({"input": "what's generative ai?"})
注意:其中用 RunnablePassthrough() 将第一次模型的输出作为第二次的输入
二:结合LCEL实现对输出的处理
之前是
首先,我们用 Pydnatic 定义一个对象:
# 用 Pydantic 定义输出的 JSON 格式 from langchain_core.pydantic_v1 import BaseModel, Field # Define your desired data structure. class Joke(BaseModel): setup: str = Field(description="question to set up a joke") punchline: str = Field(description="answer to resolve the joke")
然后,我们调用模型,并指示模型输出 JSON 格式:
from langchain_core.output_parsers import JsonOutputParser from langchain.prompts import ChatPromptTemplate chatmodel = ChatOpenAI() joke_query = "Tell me a joke." # Set up a parser + inject instructions into the prompt template. parser = JsonOutputParser(pydantic_object=Joke) prompt_template = ChatPromptTemplate.from_messages( [ ("system", "Answer the user query.\n{format_instructions}"), ("user", "{query}") ]) chain = prompt_template | chatmodel | parser #print(parser.get_format_instructions()) chain.invoke( {"query": joke_query, "format_instructions": parser.get_format_instructions() })
其中get_format_instructions指示我们如何将llm的输出进行格式化,需要注入到prompt中
补充1:两种引入prompt模板的方式其实最后都是走到langchain_core.prompts,如果要使用第二个,需要使用pip install langchain安装
from langchain_core.prompts import ChatPromptTemplate from langchain.prompts import ChatPromptTemplate
补充2:目前的例子中我们对prompt提示语的输入参数都是在最后面invoke时填充进去的,还可以使用partial()逐步的填充提示语的输入参数
# 4. 创建模板 prompt_template = ChatPromptTemplate.from_messages( [ ("system", "Answer the user query.\n{format_instructions}"), ("user", "{query}") ]) # 5. 在模板中部分填充输出要求 prompt_partial_filled = prompt_template.partial( format_instructions=parser.get_format_instructions() ) # 6. 生成调用链 chain = prompt_partial_filled | chatmodel | parser # 7. 调用模型 joke_query = "Tell me a joke." chain.invoke({"query": joke_query})
三:将结果流式输出
- 将模型设为流式输出;
- 调用采用
stream()
而非invoke()
; - 从开始接收到输出时就逐一打印。
chatmodel = ChatOpenAI( streaming=True ) prompt_template = ChatPromptTemplate.from_messages([ ("system", "You are world class technical documentation writer."), ("user", "{query}") ]) output_parser = StrOutputParser() chain = prompt_template | chatmodel | output_parser response = chain.stream({"query": "what's generative ai?"}) for value in response: print(value, end='', flush=True) #end=''使得后续的输出会紧接着前面的输出;flush=True意味着每次print调用后,输出缓存都会被清空,确保value被直接显示。
四:使用OpenAI SDK调用其他兼容/非兼容模型
(一)模型完全兼容OpenAI SDK
采用更改
openai_api_base
(alias base_url
)和model_name
来调用这些模型:from langchain_openai import ChatOpenAI api_key = userdata.get('deepseek') base_url= 'https://api.deepseek.com/v1' model_name='deepseek-chat' chatmodel = ChatOpenAI( base_url=base_url, api_key=api_key, model_name=model_name) chatmodel.invoke("what's generative ai?")
(二)模型没有完全兼容OpenAI SDK
需要有对应模型的SDK、API,调用对应模型的方法即可,以文心为例:
- 注册百度千帆账号,开启相关的模型服务,并充值。你需要获得 API KEY 与 API Secret。我们这里配置的是百度文心(ErnieBot)模型。
- 安装 Qianfan SDK:
pip install qianfan
- 设置API key、secret
- 调用对应的SDK
from langchain_community.chat_models.baidu_qianfan_endpoint import QianfanChatEndpoint chat = QianfanChatEndpoint( qianfan_ak = qf_api_key, qianfan_sk = qf_secrect_key, ) chat([HumanMessage(content="hello there, who are you?")])
五:少样本模板的构建FewShotChatMessagePromptTemplate
大语言模型是“少样本学习者”(Few shot learner),它能够直接从我们在提示语中提供的样例中学习。除了手工模拟AIMessage和HumanMessage之外,还可以通过FewShotChatMessagePromptTemplate协助完成创建少样本。
1.创建少样本
from langchain_core.prompts import ChatPromptTemplate, FewShotChatMessagePromptTemplate from langchain_openai import ChatOpenAI examples = [ {"input": "2+2", "output": "4"}, {"input": "2+3", "output": "5"}, ] # This is a prompt template used to format each individual example. example_prompt = ChatPromptTemplate.from_messages( [ ("human", "{input}"), ("ai", "{output}"), ] ) few_shot_prompt = FewShotChatMessagePromptTemplate( example_prompt=example_prompt, examples=examples, ) print(few_shot_prompt.format())
2.添加少样本到message
final_prompt = ChatPromptTemplate.from_messages( [ ("system", "You are a wondrous wizard of math."), few_shot_prompt, ("human", "{input}"), ] ) print(final_prompt.format(input="What's the square of a triangle?"))