引言:为什么需要链式调用?
在AI应用开发中,复杂任务往往需要多轮LLM(大语言模型)调用协同完成。例如:
- 生成单元测试需先解析代码逻辑→设计测试场景→生成测试代码;
- 多语言问答需将中文问题→翻译成英文→获取英文回答→再翻译回中文;
- 数据分析需先提取数据→生成可视化代码→解释分析结果。
传统方法中,这些步骤需要手动拼接API调用结果,代码冗余且难以维护。而LangChain的链式调用(Chaining) 技术通过将多个步骤封装为可复用的组件,实现自动化工作流,减少80%的胶水代码,让开发者聚焦核心逻辑。
一、链式调用核心架构:组件与工作原理
1.1 解决的核心痛点
原生API开发中,多步任务处理繁琐且易错:
# 传统多步调用示例(手动拼接)
def traditional_multistep_task(code):
# 步骤1:解析代码
explanation = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{
"role": "user", "content": f"解析代码:{
code}"}]
).choices[0].message.content
# 步骤2:生成测试计划
test_plan = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{
"role": "user", "content": f"基于解析生成测试计划:{
explanation}"}]
).choices[0].message.content
# 步骤3:生成测试代码
test_code = openai.ChatCompletion.create(
model="gpt-3.5-turbo",
messages=[{
"role": "user", "content": f"基于计划生成代码:{
test_plan}"}]
).choices[0].message.content
return test_code
问题:
- 每步需手动处理输入输出,代码冗余;
- 无统一错误处理机制,一步失败则全流程中断;
- 难以复用步骤,相同逻辑需重复编写。
LangChain链式调用通过组件化设计解决这些问题,实现自动化步骤衔接、结构化输出和可复用组件。
1.2 核心组件与关系
graph LR
A[用户输入] --> B[PromptTemplate<br>(提示模板)]
B --> C[LLMChain<br>(单步调用)]
C --> D[OutputParser<br>(输出解析器)]
D --> E[中间结果]
E --> F[SequentialChain<br>(多步协调)]
F --> G[TransformChain<br>(数据转换)]
G --> H[最终输出]
组件 | 作用 | 关键参数 |
---|---|---|
PromptTemplate |
动态生成提示语,支持变量替换 | template (模板字符串)、input_variables (变量列表) |
LLMChain |
单步LLM调用单元,结合提示模板与模型 | llm (模型实例)、prompt (提示模板) |
SequentialChain |
按顺序执行多个链,自动传递上下文 | chains (子链列表)、input_variables (输入变量)、output_variables (输出变量) |
TransformChain |
自定义数据转换逻辑(如格式清洗、合并) | transform (转换函数)、input_variables /output_variables |
OutputParser |
将LLM输出解析为结构化数据(如JSON、Pydantic模型) | parse (解析方法) |
1.3 两种基础链式模式
1. 简单顺序链(SimpleSequentialChain)
适用于单输入→单输出的线性流程,前一链的输出直接作为后一链的输入:
from langchain.chains import SimpleSequentialChain
from langchain.chat_models import ChatOpenAI
from langchain.prompts import PromptTemplate
# 初始化模型
llm = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.1)
# 步骤1:将中文问题翻译成英文
translate_prompt = PromptTemplate(
template="将以下中文问题翻译成英文:{question}",
input_variables=["question"]
)
translate_chain = LLMChain(llm=llm, prompt=translate_prompt)
# 步骤2:用英文回答问题
answer_prompt = PromptTemplate(
template="回答英文问题:{english_question}",
input_variables=["english_question"]
)
answer_chain = LLMChain(llm=llm, prompt=answer_prompt)
# 构建简单顺序链
chain = SimpleSequentialChain(
chains=[translate_chain, answer_chain],
verbose=True # 输出执行日志
)
# 执行链
result = chain.run("什么是LangChain的链式调用?")
print(result)
# 输出:LangChain's chain calling refers to the technique of connecting multiple LLM calls...
2. 复杂顺序链(SequentialChain)
支持多输入、多输出,需显式指定变量传递关系:
from langchain.chains import SequentialChain
# 步骤3:将英文回答翻译回中文
translate_back_prompt = PromptTemplate(
template="将以下英文回答翻译成中文:{english_answer}",
input_variables=["english_answer"]
)
translate_back_chain = LLMChain(
llm=llm,
prompt=translate_back_prompt,
output_key="chinese_answer" # 显式指定输出键
)
# 构建复杂顺序链
multi_chain = SequentialChain(
chains=[translate_chain, answer_chain, translate_back_chain],
input_variables=["question"], # 初始输入变量
output_variables=["chinese_answer"], # 最终输出变量
verbose=True
)
# 执行链
result = multi_chain.run("什么是LangChain的链式调用?")
print(result)
# 输出:LangChain的链式调用指的是将多个LLM调用连接起来的技术...
关键区别:
- 简单链适用于线性流程,无需显式指定变量;
- 复杂链支持多变量传递,需用
output_key
定义中间结果的键名。
二、实战案例:自动化测试生成流水线
以生成Python函数的单元测试为例,展示如何用链式调用实现“解析代码→设计测试→生成代码→合并优化”的全流程自动化。
2.1 案例架构设计
flowchart TD
A[函数代码] --> B[基础测试链<br>(正常/异常场景)]
B --> C[边界测试链<br>(负数/浮点数)]
C --> D[参数化测试链<br>(批量用例)]
D --> E[合并转换链<br>(代码整合)]
E --> F[完整测试套件]
2.2 步骤1:生成基础测试用例
解析函数逻辑,生成正常场景和异常场景的基础测试:
from langchain.prompts