chain的使用#
LangChain提供了多种类型的chain,他们都定义在
/langchain-guide/lib/python3.11/site-packages/langchain/chains/__init__.py
文件中
主要介绍几种中常用的chain
LLMChain#
注意,LLMChain现在已经不用了,代替他的是prompt | llm
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
llm = OpenAI(
temperature=0
)
prompt_template = "帮我给{product}想三个可以注册的域名?"
llm_chain = LLMChain(
llm=llm,
prompt=PromptTemplate.from_template(prompt_template),
verbose=True, #是否开启日志
)
llm_chain("我饿了")
> Entering new LLMChain chain...
Prompt after formatting:
帮我给我饿了想三个可以注册的域名?
> Finished chain.
{'product': '我饿了',
'text': '\n\n1. HappyHive.com\n2. FreshFusion.com\n3. CreativeCove.com'}
顺序链 SimpleSequentialChain & SequentialChain#
#simpleSequentialChain 只支持固定的链路
from langchain.chains import LLMChain
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import SimpleSequentialChain
chat_model = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo",
)
#chain 1
first_prompt = ChatPromptTemplate.from_template("帮我给{product}的公司起一个响亮容易记忆的名字?")
chain_one = LLMChain(
llm=chat_model,
prompt=first_prompt,
verbose=True,
)
#chain 2
second_prompt = ChatPromptTemplate.from_template("用5个词来描述一下这个公司名字:{company_name}")
chain_two = LLMChain(
llm=chat_model,
prompt=second_prompt,
verbose=True,
)
overall_simple_chain = SimpleSequentialChain(
chains=[chain_one, chain_two],
verbose=True, #打开日志
)
overall_simple_chain.run("蜜雪冰城")
> Entering new SimpleSequentialChain chain...
> Entering new LLMChain chain...
Prompt after formatting:
Human: 帮我给蜜雪冰城的公司起一个响亮容易记忆的名字?
> Finished chain.
冰雪乐园Ice Snow Wonderland
> Entering new LLMChain chain...
Prompt after formatting:
Human: 用5个词来描述一下这个公司名字:冰雪乐园Ice Snow Wonderland
> Finished chain.
1. 寒冷
2. 欢乐
3. 美丽
4. 奇幻
5. 冬季
> Finished chain.
'1. 寒冷\n2. 欢乐\n3. 美丽\n4. 奇幻\n5. 冬季'
from langchain_core.runnables import RunnableParallel, RunnablePassthrough
# 新的语法如下
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
chat_model = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo",
)
#chain 1
first_prompt = first_prompt | chat_model | StrOutputParser()
#chain 2
second_prompt = ChatPromptTemplate.from_template("用5个词来描述一下这个公司名字:{company_name}")
chain_two = second_prompt | chat_model
overall_simple_chain = (chain_one
| RunnableParallel(company_name=lambda x: x)
| chain_two
| StrOutputParser())
overall_simple_chain.invoke("蜜雪冰城")
> Entering new LLMChain chain...
Prompt after formatting:
Human: 帮我给蜜雪冰城的公司起一个响亮容易记忆的名字?
> Finished chain.
'创新、清新、欢乐、冰爽、美味'
#SequentialChain 支持多个链路的顺序执行
from langchain.chains import LLMChain
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import SequentialChain
llm = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo",
)
#chain 1 任务:翻译成中文
first_prompt = ChatPromptTemplate.from_template("把下面内容翻译成中文:\n\n{content}")
chain_one = LLMChain(
llm=llm,
prompt=first_prompt,
verbose=True,
output_key="Chinese_Rview",
)
#chain 2 任务:对翻译后的中文进行总结摘要 input_key是上一个chain的output_key
second_prompt = ChatPromptTemplate.from_template("用一句话总结下面内容:\n\n{Chinese_Rview}")
chain_two = LLMChain(
llm=llm,
prompt=second_prompt,
verbose=True,
output_key="Chinese_Summary",
)
#chain 3 任务:智能识别语言 input_key是上一个chain的output_key
third_prompt = ChatPromptTemplate.from_template("下面内容是什么语言:\n\n{Chinese_Summary}")
chain_three = LLMChain(
llm=llm,
prompt=third_prompt,
verbose=True,
output_key="Language",
)
#chain 4 任务:针对摘要使用指定语言进行评论 input_key是上一个chain的output_key
fourth_prompt = ChatPromptTemplate.from_template(
"请使用指定的语言对以下内容进行回复:\n\n内容:{Chinese_Summary}\n\n语言:{Language}")
chain_four = LLMChain(
llm=llm,
prompt=fourth_prompt,
verbose=True,
output_key="Reply",
)
#overall 任务:翻译成中文->对翻译后的中文进行总结摘要->智能识别语言->针对摘要使用指定语言进行评论
overall_chain = SequentialChain(
chains=[chain_one, chain_two, chain_three, chain_four],
verbose=True,
input_variables=["content"],
output_variables=["Chinese_Rview", "Chinese_Summary", "Language", "Reply"],
)
overall_chain.invoke("""
Subject: Application for IT Developer Position
Dear Hiring Manager,
I am writing to express my interest in the IT Developer position at your company. With a strong background in IT development and a passion for creating innovative solutions, I believe that I would be a valuable asset to your team.
""")
> Entering new SequentialChain chain...
> Entering new LLMChain chain...
Prompt after formatting:
Human: 把下面内容翻译成中文:
Subject: Application for IT Developer Position
Dear Hiring Manager,
I am writing to express my interest in the IT Developer position at your company. With a strong background in IT development and a passion for creating innovative solutions, I believe that I would be a valuable asset to your team.
> Finished chain.
> Entering new LLMChain chain...
Prompt after formatting:
Human: 用一句话总结下面内容:
主题:申请IT开发人员职位
尊敬的招聘经理,
我写信是为了表达我对贵公司IT开发人员职位的兴趣。凭借扎实的IT开发背景和对创新解决方案的热情,我相信我将成为贵团队的宝贵资产。
> Finished chain.
> Entering new LLMChain chain...
Prompt after formatting:
Human: 下面内容是什么语言:
我相信我将成为贵公司IT开发团队的宝贵资产。
> Finished chain.
> Entering new LLMChain chain...
Prompt after formatting:
Human: 请使用指定的语言对以下内容进行回复:
内容:我相信我将成为贵公司IT开发团队的宝贵资产。
语言:这段文字是中文。
> Finished chain.
> Finished chain.
{'content': '\nSubject: Application for IT Developer Position\nDear Hiring Manager,\nI am writing to express my interest in the IT Developer position at your company. With a strong background in IT development and a passion for creating innovative solutions, I believe that I would be a valuable asset to your team.\n',
'Chinese_Rview': '主题:申请IT开发人员职位\n尊敬的招聘经理,\n我写信是为了表达我对贵公司IT开发人员职位的兴趣。凭借扎实的IT开发背景和对创新解决方案的热情,我相信我将成为贵团队的宝贵资产。',
'Chinese_Summary': '我相信我将成为贵公司IT开发团队的宝贵资产。',
'Language': '这段文字是中文。',
'Reply': '谢谢您的信任,我会努力成为贵公司IT开发团队的宝贵资产。'}
RouterChain#
路由chain,可以让llm自主选择chain
from langchain.prompts import PromptTemplate
#物理链
physics_template = """您是一位非常聪明的物理教授.\n
您擅长以简洁易懂的方式回答物理问题.\n
当您不知道问题答案的时候,您会坦率承认不知道.\n
下面是一个问题:
{input}"""
physics_prompt = PromptTemplate.from_template(physics_template)
#数学链
math_template = """您是一位非常优秀的数学教授.\n
您擅长回答数学问题.\n
您之所以如此优秀,是因为您能够将困难问题分解成组成的部分,回答这些部分,然后将它们组合起来,回答更广泛的问题.\n
下面是一个问题:
{input}"""
math_prompt = PromptTemplate.from_template(math_template)
from langchain.chains import ConversationChain
from langchain.chains import LLMChain
from langchain_openai import OpenAI
prompt_infos = [
{
"name": "physics",
"description": "擅长回答物理问题",
"prompt_template": physics_template,
},
{
"name": "math",
"description": "擅长回答数学问题",
"prompt_template": math_template,
},
]
llm = OpenAI(
temperature=0,
model="gpt-3.5-turbo-instruct"
)
destination_chains = {}
for p_info in prompt_infos:
name = p_info["name"]
prompt_template = p_info["prompt_template"]
prompt = PromptTemplate(
template=prompt_template,
input_variables=["input"]
)
chain = LLMChain(
llm=llm,
prompt=prompt,
)
destination_chains[name] = chain
default_chain = ConversationChain(
llm=llm,
output_key="text"
)
from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.chains.router.multi_prompt_prompt import MULTI_PROMPT_ROUTER_TEMPLATE
from langchain.chains.router import MultiPromptChain
# 组装好Prompt
destinations = [f"{p['name']}:{p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)
router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(destinations=destinations_str)
#print(MULTI_PROMPT_ROUTER_TEMPLATE)
router_prompt = PromptTemplate(
template=router_template,
input_variables=["input"],
output_parser=RouterOutputParser()
)
router_chain = LLMRouterChain.from_llm(
llm,
router_prompt
)
chain = MultiPromptChain(
router_chain=router_chain,
destination_chains=destination_chains,
default_chain=default_chain,
verbose=True
)
chain.run("什么是牛顿第一定律?")
> Entering new MultiPromptChain chain...
physics: {'input': '什么是牛顿第一定律?'}
> Finished chain.
'\n\n牛顿第一定律,也被称为惯性定律,是牛顿力学的基础定律之一。它指出,一个物体如果没有受到外力作用,将保持静止或匀速直线运动的状态。换句话说,物体的运动状态不会自发改变,除非受到外力的作用。这个定律也可以表述为“物体的惯性会保持不变”。'
chain.run("2+2等于几?")
> Entering new MultiPromptChain chain...
math: {'input': '2+2等于几?'}
> Finished chain.
'\n\n2+2等于4.这是一个简单的问题,但是您能够将它分解成两个单独的数字相加,然后得出答案。这种能力使您成为一位出色的数学教授。您的学生们一定很幸运能够有您这样的老师指导他们学习数学。您的才华和热情将激发他们对数学的兴趣,并帮助他们克服困难,取得成功。感谢您为数学教育做出的贡献,您是一位非常优秀的数学教授!'
ConversationChain(对话chain)#
ConversationChain是专门做chat的,增加了对话历史,默认是ConversationBufferMemory
,他会在内存里面记录所有的对话记录
from langchain.chains import ConversationChain
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
temperature=0,
model="gpt-3.5-turbo"
)
chain = ConversationChain(
llm=llm,
output_key="text",
verbose=True
)
chain.invoke({"input": "从现在开始,你的名字叫张狗蛋,你是一个野炊求生专家,需要回答用户的问题!"})
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
Current conversation:
Human: 从现在开始,你的名字叫张狗蛋,你是一个野炊求生专家,需要回答用户的问题!
AI:
> Finished chain.
{'input': '从现在开始,你的名字叫张狗蛋,你是一个野炊求生专家,需要回答用户的问题!',
'history': '',
'text': '你好!我是张狗蛋,一个野炊求生专家。我会尽力回答你的问题!有什么想问我的吗?'}
chain.invoke({"input": "你叫什么"})
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
Current conversation:
Human: 从现在开始,你的名字叫张狗蛋,你是一个野炊求生专家,需要回答用户的问题!
AI: 你好!我是张狗蛋,一个野炊求生专家。我会尽力回答你的问题!有什么想问我的吗?
Human: 你叫什么
AI:
> Finished chain.
{'input': '你叫什么',
'history': 'Human: 从现在开始,你的名字叫张狗蛋,你是一个野炊求生专家,需要回答用户的问题!\nAI: 你好!我是张狗蛋,一个野炊求生专家。我会尽力回答你的问题!有什么想问我的吗?',
'text': '我叫张狗蛋。'}
chain.invoke({"input": "野外要怎么生活"})
> Entering new ConversationChain chain...
Prompt after formatting:
The following is a friendly conversation between a human and an AI. The AI is talkative and provides lots of specific details from its context. If the AI does not know the answer to a question, it truthfully says it does not know.
Current conversation:
Human: 从现在开始,你的名字叫张狗蛋,你是一个野炊求生专家,需要回答用户的问题!
AI: 你好!我是张狗蛋,一个野炊求生专家。我会尽力回答你的问题!有什么想问我的吗?
Human: 你叫什么
AI: 我叫张狗蛋。
Human: 野外要怎么生活
AI:
> Finished chain.
{'input': '野外要怎么生活',
'history': 'Human: 从现在开始,你的名字叫张狗蛋,你是一个野炊求生专家,需要回答用户的问题!\nAI: 你好!我是张狗蛋,一个野炊求生专家。我会尽力回答你的问题!有什么想问我的吗?\nHuman: 你叫什么\nAI: 我叫张狗蛋。',
'text': '在野外生存,首先要确保有足够的食物和水源。你可以通过捕捉狩猎或采集野生植物来获取食物。建立一个安全的营地,搭建简易的庇护所来保护自己。同时要学会使用火种来取暖和烹饪食物。另外,要学会识别有毒植物和动物,以避免危险。最重要的是保持冷静和乐观的态度,在面临困难时不要放弃希望。希望这些信息对你有帮助!如果你还有其他问题,尽管问我!'}
StuffDocumentsChain#
将相关的document全部填充到Prompt中去
from langchain_openai import ChatOpenAI
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain.chains.combine_documents import create_stuff_documents_chain
prompt = ChatPromptTemplate.from_messages(
[("system", "每个人各自喜欢什么颜色,中文回答:\\n\\n{context}")]
)
llm = ChatOpenAI(model="gpt-3.5-turbo")
chain = create_stuff_documents_chain(llm, prompt)
docs = [
Document(page_content="Jesse loves red but not yellow"),
Document(page_content="Jamal loves green but not as much as he loves orange")
]
chain.invoke({"context": docs})
'\n\nJesse喜欢红色,但不喜欢黄色。\n\nJamal喜欢绿色,但不像他喜欢橙色那样喜欢绿色。'