LLM学习:langchain架构——chain
1、什么是chain?
在LangChain中,Chain(链)是将多个组件(Components)按特定顺序连接起来,实现复杂任务的工作流(Workflow)或管道(Pipeline)。它是LangChain框架的基石和核心抽象。
2、多种chain的类型及使用
2.1、路由Chain(RouterChain)
from langchain.chains.router import LLMRouterChain, MultiRouteChain
from langchain.chains.router.llm_router import RouterOutputParser
from langchain.prompts import PromptTemplate
from langchain_community.llms import Tongyi
from langchain.chains import LLMChain
import os# 初始化通义千问模型
api_key = os.getenv("DASHSCOPE_API_KEY")
llm = Tongyi(dashscope_api_key=api_key,model_name="qwen-turbo"
)# ===== 1. 准备目标处理链 =====
# 物理专家链
physics_prompt = PromptTemplate(template="你是一位物理学家,用专业术语回答,并且在回答问题之前把自己的身份报一下,如物理学家:{input}",input_variables=["input"]
)
physics_chain = LLMChain(llm=llm, prompt=physics_prompt)# 数学专家链
math_prompt = PromptTemplate(template="你是一位数学家,逐步解答,并且在回答问题之前把自己的身份报一下,如数学家:{input}",input_variables=["input"]
)
math_chain = LLMChain(llm=llm, prompt=math_prompt)# 默认链(兜底)
default_prompt = PromptTemplate(template="{input}",input_variables=["input"]
)
default_chain = LLMChain(llm=llm, prompt=default_prompt)# ===== 2. 构建路由链 =====
# 修改路由模板,使其输出符合 RouterOutputParser 期望的 JSON 格式
router_template = '''
你是一个专业路由助手,根据问题类型选择处理链。可选项:
[physics] - 涉及力、热、光、电磁等物理现象
[math] - 包含公式、计算、几何、代数等数学问题
[default] - 其他类型问题当前输入:{input}
请严格按照以下 JSON 格式输出,不要添加任何其他内容,注意一定要输出destination:
{{"destination": "选项标识符", "next_inputs": "{input}"}}
例如:{{"destination": "math", "next_inputs": "计算球体体积公式是什么?"}}示例:
输入:计算球体体积公式是什么?
输出:{{"destination": "math", "next_inputs": "计算球体体积公式是什么?"}}输入:解释量子纠缠现象
输出:{{"destination": "physics", "next_inputs": "解释量子纠缠现象"}}输入:推荐一本经典科幻小说
输出:{{"destination": "default", "next_inputs": "推荐一本经典科幻小说"}}
'''router_chain = LLMRouterChain.from_llm(llm=llm,prompt=PromptTemplate(template=router_template,input_variables=["input"],output_parser=RouterOutputParser())
)# ===== 3. 组装路由系统 =====
multi_chain = MultiRouteChain(router_chain=router_chain,destination_chains={"physics": physics_chain,"math": math_chain},default_chain=default_chain,verbose=True)# ===== 4. 测试路由 =====
inputs = ["计算球体体积公式是什么?", # 预期路由到math"解释量子纠缠现象", # 预期路由到physics"推荐一本经典科幻小说" # 预期路由到default
]# ... existing code ...
for query in inputs:print(f"输入:{query}")result = multi_chain.invoke({"input": query})# 打印完整结果以检查其实际结构print(f"完整结果: {result}")# 根据实际输出结构调整以下代码if isinstance(result, dict):# 检查是否存在 'destination' 键if 'destination' in result:print(f"路由结果:{result['destination'].upper()}链")# 检查是否存在 'answer' 或 'text' 键来获取回答answer = result.get('answer', result.get('text', 'No answer provided'))print(f"回答:{answer}")# 如果存在 'output' 键,则进一步检查其内容elif 'output' in result:output_content = result['output']if isinstance(output_content, dict) and 'destination' in output_content:print(f"路由结果:{output_content['destination'].upper()}链")answer = output_content.get('answer', output_content.get('text', 'No answer provided'))print(f"回答:{answer}")else:print(f"路由结果:未知链")print(f"回答:{output_content}")else:print(f"路由结果:未知链")print(f"回答:{result}")else:print(f"路由结果:未知链")print(f"回答:{result}")print()
# ... existing code ...
2.2、顺序链
在 LangChain 的 SimpleSequentialChain 中,链的排列顺序会直接影响最终输出结果。这是因为该链的核心机制是严格按声明顺序执行链,前一个链的输出会作为后一个链的输入。
from langchain.chains import LLMChain, SimpleSequentialChain
from langchain.prompts import PromptTemplate
from langchain_community.llms import Tongyi
import os# 初始化通义千问模型
api_key = os.getenv("DASHSCOPE_API_KEY")
llm = Tongyi(dashscope_api_key=api_key,model_name="qwen-turbo-latest",temperature=0.7
)# 第一个链:生成一个创意概念
concept_template = """你是一个创意专家,请为以下主题生成一个独特的概念:
主题: {input}
概念:"""
concept_prompt = PromptTemplate(template=concept_template, input_variables=["input"])
concept_chain = LLMChain(llm=llm, prompt=concept_prompt)# 第二个链:基于概念生成详细描述
description_template = """你是一个内容策划专家,请基于以下概念生成一段详细的描述:
概念: {input}
详细描述:"""
description_prompt = PromptTemplate(template=description_template, input_variables=["input"])
description_chain = LLMChain(llm=llm, prompt=description_prompt)# 第三个链:为描述添加标题
headline_template = """你是一个标题专家,请为以下描述生成一个吸引人的标题:
描述: {input}
标题:"""
headline_prompt = PromptTemplate(template=headline_template, input_variables=["input"])
headline_chain = LLMChain(llm=llm, prompt=headline_prompt)# 创建 SimpleSequentialChain
# verbose=True 用于显示执行过程
overall_chain = SimpleSequentialChain(chains=[concept_chain, description_chain, headline_chain],verbose=True
)# 测试案例
if __name__ == "__main__":# 输入主题input_topic = "人工智能在医疗领域的应用"print(f"输入主题: {input_topic}")print("=" * 50)# 执行链式调用result = overall_chain.invoke(input_topic)print("=" * 50)print(f"最终输出: {result['output']}")
2.3 四大文档链的对比
选择建议:
文档短 → Stuff
文档长且需逻辑连贯 → Refine
海量独立文档 → MapReduce
需筛选最佳答案 → MapRerank