构建第一条链:简单的问答链

核心知识点讲解

什么是链(Chain)?

在LangChain中,链是将多个组件组合在一起以完成特定任务的方式。链可以是简单的(如将提示词模板与语言模型连接),也可以是复杂的(如将多个链组合在一起处理复杂任务)。

基本链的组成

一个基本的问答链通常由以下组件组成:

  1. 提示词模板(Prompt Template):定义问题的格式和上下文
  2. 语言模型(Language Model):处理输入并生成回答
  3. 输出解析器(Output Parser):(可选)处理模型输出

链的类型

LangChain提供了多种类型的链,适合不同的场景:

  • LLMChain:最基本的链,将提示词模板和语言模型组合
  • SequentialChain:按顺序执行多个链
  • RouterChain:根据输入选择不同的链
  • RetrievalQA:结合检索和问答的链

实用案例分析

案例1:构建基本的问答链

from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain

# 1. 创建提示词模板
prompt = PromptTemplate(
    input_variables=["question"],
    template="请详细回答以下问题:{question}"
)

# 2. 初始化语言模型
llm = OpenAI(temperature=0.7)

# 3. 创建LLM链
qa_chain = LLMChain(
    llm=llm,
    prompt=prompt,
    verbose=True  # 启用详细输出
)

# 4. 运行链
response = qa_chain.run("什么是人工智能?")
print("回答:", response)

案例2:带上下文的问答链

from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain

# 1. 创建带上下文的提示词模板
prompt = PromptTemplate(
    input_variables=["context", "question"],
    template="基于以下上下文回答问题:\n\n上下文:{context}\n\n问题:{question}\n\n回答:"
)

# 2. 初始化语言模型
llm = OpenAI(temperature=0)

# 3. 创建LLM链
context_qa_chain = LLMChain(
    llm=llm,
    prompt=prompt,
    verbose=True
)

# 4. 准备上下文和问题
context = "人工智能(Artificial Intelligence,简称AI)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能的发展历史可以分为几个阶段:1956年达特茅斯会议标志着人工智能的诞生;1970年代末到1980年代初,专家系统兴起;1990年代,机器学习技术取得突破;2010年代以来,深度学习技术的发展推动了人工智能的快速进步。"

question = "人工智能的发展历史分为哪几个阶段?"

# 5. 运行链
response = context_qa_chain.run(
    context=context,
    question=question
)
print("回答:", response)

案例3:使用聊天模型的问答链

from langchain.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain

# 1. 创建聊天提示词模板
system_prompt = SystemMessagePromptTemplate.from_template(
    "你是一个专业的AI助手,擅长回答各种问题,提供准确、详细的信息。"
)

human_prompt = HumanMessagePromptTemplate.from_template(
    "{question}"
)

chat_prompt = ChatPromptTemplate.from_messages([
    system_prompt,
    human_prompt
])

# 2. 初始化聊天模型
chat_model = ChatOpenAI(temperature=0.7)

# 3. 创建聊天链
chat_qa_chain = LLMChain(
    llm=chat_model,
    prompt=chat_prompt,
    verbose=True
)

# 4. 运行链
response = chat_qa_chain.run("什么是机器学习?")
print("回答:", response)

案例4:带输出解析的问答链

from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain
from langchain.output_parsers import StructuredOutputParser, ResponseSchema

# 1. 定义响应模式
response_schemas = [
    ResponseSchema(name="answer", description="问题的详细回答"),
    ResponseSchema(name="sources", description="回答的参考来源,用逗号分隔"),
    ResponseSchema(name="confidence", description="回答的置信度,0-100之间的数字")
]

# 2. 创建输出解析器
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)

# 3. 创建提示词模板
prompt = PromptTemplate(
    input_variables=["question"],
    template="请详细回答以下问题,并提供参考来源和置信度(0-100):\n\n问题:{question}\n\n{format_instructions}",
    partial_variables={"format_instructions": output_parser.get_format_instructions()}
)

# 4. 初始化语言模型
llm = OpenAI(temperature=0.7)

# 5. 创建链
structured_qa_chain = LLMChain(
    llm=llm,
    prompt=prompt,
    output_parser=output_parser,
    verbose=True
)

# 6. 运行链
response = structured_qa_chain.run("什么是深度学习?")
print("结构化回答:")
print(f"答案: {response['answer']}")
print(f"来源: {response['sources']}")
print(f"置信度: {response['confidence']}")

代码解析

案例1:基本问答链

  1. 提示词模板:创建了一个简单的提示词模板,接收一个question变量
  2. 语言模型:使用OpenAI模型,设置temperature为0.7以获得一定的创造性
  3. LLMChain:将提示词模板和语言模型组合成链,启用verbose模式以查看详细过程
  4. 运行链:使用run方法传入问题,获取回答

案例2:带上下文的问答链

  1. 提示词模板:创建了一个带上下文的提示词模板,接收contextquestion两个变量
  2. 语言模型:设置temperature为0以获得更准确、一致的回答
  3. 运行链:同时传入上下文和问题,模型基于提供的上下文生成回答

案例3:聊天模型问答链

  1. 聊天提示词:使用ChatPromptTemplate创建聊天格式的提示词,包含系统消息和人类消息
  2. 聊天模型:使用ChatOpenAI模型,适合对话场景
  3. 运行链:传入问题,模型以聊天方式生成回答

案例4:带输出解析的问答链

  1. 响应模式:定义了回答、来源和置信度三个字段的响应模式
  2. 输出解析器:创建StructuredOutputParser来解析结构化输出
  3. 提示词模板:包含格式说明,指导模型生成结构化输出
  4. 运行链:获取解析后的结构化回答,包含多个字段

高级技巧

1. 使用LCEL语法构建链

LangChain Expression Language (LCEL)提供了更简洁的方式来构建链:

from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI

# 使用LCEL语法
prompt = PromptTemplate(
    input_variables=["question"],
    template="请回答:{question}"
)

llm = OpenAI(temperature=0.7)

# 使用|操作符构建链
chain = prompt | llm

# 运行链
response = chain.invoke({"question": "什么是人工智能?"})
print(response)

2. 批量处理问题

对于多个问题,可以使用generate方法批量处理:

from langchain.prompts import PromptTemplate
from langchain.llms import OpenAI
from langchain.chains import LLMChain

prompt = PromptTemplate(
    input_variables=["question"],
    template="请回答:{question}"
)

llm = OpenAI(temperature=0.7)
chain = LLMChain(llm=llm, prompt=prompt)

# 批量处理多个问题
questions = [
    {"question": "什么是人工智能?"},
    {"question": "什么是机器学习?"},
    {"question": "什么是深度学习?"}
]

responses = chain.generate(questions)

for i, result in enumerate(responses.generations):
    print(f"问题{i+1}: {questions[i]['question']}")
    print(f"回答: {result[0].text}")
    print()

3. 自定义链

对于复杂场景,可以创建自定义链:

from langchain.chains import Chain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
from typing import Dict, List, Any

class CustomQAChain(Chain):
    llm: OpenAI
    prompt: PromptTemplate
    
    @property
    def input_keys(self) -> List[str]:
        return ["question"]
    
    @property
    def output_keys(self) -> List[str]:
        return ["answer", "follow_up_questions"]
    
    def _call(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
        question = inputs["question"]
        
        # 生成回答
        answer_prompt = self.prompt.format(question=question)
        answer = self.llm(answer_prompt)
        
        # 生成后续问题
        follow_up_prompt = f"基于问题 '{question}' 和回答 '{answer}',生成3个相关的后续问题,用逗号分隔:"
        follow_up_questions = self.llm(follow_up_prompt).split(',')
        follow_up_questions = [q.strip() for q in follow_up_questions]
        
        return {
            "answer": answer,
            "follow_up_questions": follow_up_questions
        }

# 使用自定义链
prompt = PromptTemplate(
    input_variables=["question"],
    template="请详细回答:{question}"
)

llm = OpenAI(temperature=0.7)

custom_chain = CustomQAChain(
    llm=llm,
    prompt=prompt
)

# 运行链
result = custom_chain.run("什么是人工智能?")
print(f"回答: {result['answer']}")
print(f"后续问题: {result['follow_up_questions']}")

总结

构建简单的问答链是使用LangChain的基础,通过本集的学习,我们掌握了:

  1. 基本链的构建:使用LLMChain将提示词模板和语言模型组合
  2. 不同类型的链:基本问答链、带上下文的问答链、聊天模型链、带输出解析的链
  3. 高级技巧:使用LCEL语法、批量处理、自定义链
  4. 参数配置:如何设置模型参数以获得不同风格的回答

这些知识为我们后续构建更复杂的智能体系统奠定了基础。在接下来的几集中,我们将学习LangChain Expression Language (LCEL)的详细语法,以及如何使用它构建更复杂的链。

课后思考

  1. 如何根据不同类型的问题选择合适的提示词模板?
  2. 温度参数(temperature)对回答有什么影响?如何选择合适的值?
  3. 什么时候应该使用聊天模型而不是基础语言模型?
  4. 如何处理模型回答中的错误或不准确信息?

在下一集中,我们将深入学习LangChain Expression Language (LCEL)语法,掌握更高级的链构建技巧。

« 上一篇 深入LangChain:模型封装与输出解析器 下一篇 » LangChain Expression Language(LCEL)语法精讲