LangChain简明教程(7)

《LangChain简明教程》系列文章目录

  1. LangChain简明教程(1)
  2. LangChain简明教程(2)
  3. LangChain简明教程(3)
  4. LangChain简明教程(4)
  5. LangChain简明教程(5)
  6. LangChain简明教程(6)

模块 IV:链

LangChain 是一个专为在复杂应用中利用大型语言模型(LLMs)而设计的工具。它提供了用于创建组件链的框架,其中包括 LLMs 和其他类型的组件。LangChain 主要包含两个核心框架:

  • LangChain Expression Language (LCEL)
  • Legacy Chain interface

LangChain Expression Language (LCEL) 是一种语法,能够直观地实现链式组合。它支持许多高级功能,例如流式传输、异步调用、批处理、并行化、重试、回退和追踪。例如,你可以使用 LCEL 将提示词(prompt)、模型(model)和输出解析器(output parser)组合在一起,如下方代码所示:

from langchain.prompts import ChatPromptTemplate
from langchain.schema import StrOutputParser

model = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
prompt = ChatPromptTemplate.from_messages([
    ("system", "You're a very knowledgeable historian who provides accurate and eloquent answers to historical questions."),
    ("human", "{question}")
])
runnable = prompt | model | StrOutputParser()

for chunk in runnable.stream({"question": "What are the seven wonders of the world"}):
    print(chunk, end="", flush=True)

在这里插入图片描述

或者,LLMChain 是一个类似于 LCEL 的选项,用于组合组件。以下是 LLMChain 的示例:

from langchain.chains import LLMChain

chain = LLMChain(llm=model, prompt=prompt, output_parser=StrOutputParser())
chain.run(question="What are the seven wonders of the world")

在 LangChain 中,链(Chains)还可以通过引入 Memory 对象来实现状态化。这使得数据可以在多次调用之间持久化,如下例所示:

from langchain.chains import ConversationChain
from langchain.memory import ConversationBufferMemory

conversation = ConversationChain(llm=chat, memory=ConversationBufferMemory())
conversation.run("Answer briefly. What are the first 3 colors of a rainbow?")
conversation.run("And the next 4?")

LangChain 还支持与 OpenAI 的函数调用 API 集成,这在获取结构化输出以及在链中执行函数时非常有用。要获取结构化输出,你可以使用 Pydantic 类或 JsonSchema 来指定它们,如下所示:

from langchain.pydantic_v1 import BaseModel, Field
from langchain.chains.openai_functions import create_structured_output_runnable
from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate

class Person(BaseModel):
    name: str = Field(..., description="The person's name")
    age: int = Field(..., description="The person's age")
    fav_food: Optional[str] = Field(None, description="The person's favorite food")

llm = ChatOpenAI(model="gpt-4", temperature=0)
prompt = ChatPromptTemplate.from_messages([
    # Prompt messages here
])

runnable = create_structured_output_runnable(Person, llm, prompt)
runnable.invoke({"input": "Sally is 13"})

对于结构化输出,还可以使用基于 LLMChain 的传统方法来实现:

from langchain.chains.openai_functions import create_structured_output_chain

class Person(BaseModel):
    name: str = Field(..., description="The person's name")
    age: int = Field(..., description="The person's age")

chain = create_structured_output_chain(Person, llm, prompt, verbose=True)
chain.run("Sally is 13")

在这里插入图片描述

LangChain 利用 OpenAI 函数创建了多种用于不同目的的特定链。这些链包括用于提取、标注、OpenAPI 以及带引用的问答(QA)等场景。

在提取的场景中,其过程与结构化输出链类似,但重点在于信息或实体的提取。对于标注,其目标是为文档打上诸如情感、语言、风格、涵盖主题或政治倾向等类别的标签。

下面通过一段 Python 代码来演示 LangChain 中标注的工作原理。该过程首先需要安装必要的软件包并设置环境:

pip install langchain openai
# Set env var OPENAI_API_KEY or load from a .env file:
# import dotenv
# dotenv.load_dotenv()

from langchain.chat_models import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import create_tagging_chain, create_tagging_chain_pydantic

标注的 schema 被定义出来,指定了属性及其预期类型:

schema = {
    "properties": {
        "sentiment": {"type": "string"},
        "aggressiveness": {"type": "integer"},
        "language": {"type": "string"},
    }
}

llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
chain = create_tagging_chain(schema, llm)

通过不同输入运行标注链的示例展示了模型在解读情感、语言和攻击性方面的能力:

inp = "Estoy increiblemente contento de haberte conocido! Creo que seremos muy buenos amigos!"
chain.run(inp)
# {'sentiment': 'positive', 'language': 'Spanish'}

inp = "Estoy muy enojado con vos! Te voy a dar tu merecido!"
chain.run(inp)
# {'sentiment': 'enojado', 'aggressiveness': 1, 'language': 'es'}

为了实现更精细的控制,可以更具体地定义 schema,包括可能的值、描述和必填属性。下面展示了这种增强控制的一个示例:

schema = {
    "properties": {
        # Schema definitions here
    },
    "required": ["language", "sentiment", "aggressiveness"],
}

chain = create_tagging_chain(schema, llm)

Pydantic schemas 也可以用于定义标注标准,提供了一种 Pythonic 的方式来指定所需的属性和类型:

在 LangChain 中为实现标注功能定义 schema 时,你可以使用 Pydantic 类或 JsonSchema 来明确地定义你希望从文本中提取的标签属性及它们的数据类型。例如,如果你想要标注文档的情感、语言和主题,你可以定义一个包含这些属性的 schema,并指定每个属性的类型,如下所示的例子:

from enum import Enum
from pydantic import BaseModel, Field

class Tags(BaseModel):
    # Class fields here
    sentiment: str
    language: str
    topics: list
chain = create_tagging_chain_pydantic(Tags, llm)

这段代码定义了一个名为 Tags 的 Pydantic 类,其中包含了三个属性:sentiment(情感)、language(语言)和 topics(主题),并分别指定了它们的类型为字符串(str)和列表(list)。这样的 schema 可以帮助你在处理文本标注任务时确保数据的一致性和正确性。

此外,LangChain 的元数据标注器文档转换器可以用于从 LangChain 文档中提取元数据,功能类似于标注链,但专门应用于 LangChain 文档。

引用检索来源 是 LangChain 的另一项功能,利用 OpenAI 函数从文本中提取引用。以下代码展示了这一功能:

from langchain.chains import create_citation_fuzzy_match_chain
from langchain.chat_models import ChatOpenAI

llm = ChatOpenAI(temperature=0, model="gpt-3.5-turbo-0613")
chain = create_citation_fuzzy_match_chain(llm)
# Further code for running the chain and displaying results

在 LangChain 中,大型语言模型(LLM)应用中的链式操作通常涉及将提示模板(prompt template)与 LLM 结合,并可选地加入输出解析器(output parser)。推荐的方式是使用 LangChain 表达式语言(LCEL),尽管传统的 LLMChain 方法也仍然支持。

通过 LCEL,BasePromptTemplateBaseLanguageModelBaseOutputParser 都实现了 Runnable 接口,可以轻松地通过管道(pipe)将它们连接在一起。以下是一个示例:

from langchain.prompts import PromptTemplate
from langchain.chat_models import ChatOpenAI
from langchain.schema import StrOutputParser

prompt = PromptTemplate.from_template(
    "What is a good name for a company that makes {product}?"
)
runnable = prompt | ChatOpenAI() | StrOutputParser()
runnable.invoke({"product": "colorful socks"})
# Output: 'VibrantSocks'

在 LangChain 中,路由(Routing) 可以创建非确定性链,其中前一个步骤的输出决定了下一个步骤。这有助于在与大型语言模型(LLM)的交互中构建结构并保持一致性。例如,如果你有两个针对不同类型问题优化的模板,可以根据用户输入选择合适的模板。

以下是如何使用 LCEL 和 RunnableBranch 实现这一功能的示例。RunnableBranch 通过一组(条件,可运行对象)对以及一个默认的可运行对象进行初始化:

from langchain.chat_models import ChatOpenAI
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnableBranch
# Code for defining physics_prompt and math_prompt

general_prompt = PromptTemplate.from_template(
    "You are a helpful assistant. Answer the question as accurately as you can.\n\n{input}"
)
prompt_branch = RunnableBranch(
    (lambda x: x["topic"] == "math", math_prompt),
    (lambda x: x["topic"] == "physics", physics_prompt),
    general_prompt,
)

# More code for setting up the classifier and final chain

最终的链通过多种组件构建,例如主题分类器(topic classifier)、提示分支(prompt branch)和输出解析器(output parser),以根据输入的主题来确定流程:

from operator import itemgetter
from langchain.schema.output_parser import StrOutputParser
from langchain.schema.runnable import RunnablePassthrough

final_chain = (
    RunnablePassthrough.assign(topic=itemgetter("input") | classifier_chain)
    | prompt_branch
    | ChatOpenAI()
    | StrOutputParser()
)

final_chain.invoke(
    {
        "input": "What is the first prime number greater than 40 such that one plus the prime number is divisible by 3?"
    }
)
# Output: Detailed answer to the math question

在语言模型领域,一种常见的做法是通过一系列后续调用来跟进初始调用,其中将一个调用的输出作为下一个调用的输入。这种顺序方法在你希望基于之前交互生成的信息进行构建时特别有用。尽管 LangChain 表达式语言(LCEL)是创建这些序列的推荐方法,但为了向后兼容,SequentialChain 方法仍然被记录在案。

为了说明这一点,我们考虑一个场景:首先生成一部戏剧的概要,然后基于该概要生成一篇评论。使用 Python 的 langchain.prompts,我们创建两个 PromptTemplate 实例:一个用于生成概要,另一个用于生成评论。以下是设置这些模板的代码:

from langchain.prompts import PromptTemplate

synopsis_prompt = PromptTemplate.from_template(
    "You are a playwright. Given the title of play, it is your job to write a synopsis for that title.\n\nTitle: {title}\nPlaywright: This is a synopsis for the above play:"
)

review_prompt = PromptTemplate.from_template(
    "You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.\n\nPlay Synopsis:\n{synopsis}\nReview from a New York Times play critic of the above play:"
)

在 LCEL 方法中,我们将这些提示与 ChatOpenAIStrOutputParser 连接起来,创建一个先生成概要再生成评论的序列。代码片段如下:

from langchain.chat_models import ChatOpenAI
from langchain.schema import StrOutputParser

llm = ChatOpenAI()
chain = (
    {"synopsis": synopsis_prompt | llm | StrOutputParser()}
    | review_prompt
    | llm
    | StrOutputParser()
)
chain.invoke({"title": "Tragedy at sunset on the beach"})

对于涉及更复杂序列的场景,SequentialChain 方法便派上了用场。它允许多个输入和输出。例如,考虑一个需要根据戏剧的标题和时代生成概要的情况。以下是我们可能设置它的方式:

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

llm = OpenAI(temperature=0.7)

synopsis_template = "You are a playwright. Given the title of play and the era it is set in, it is your job to write a synopsis for that title.\n\nTitle: {title}\nEra: {era}\nPlaywright: This is a synopsis for the above play:"
synopsis_prompt_template = PromptTemplate(input_variables=["title", "era"], template=synopsis_template)
synopsis_chain = LLMChain(llm=llm, prompt=synopsis_prompt_template, output_key="synopsis")

review_template = "You are a play critic from the New York Times. Given the synopsis of play, it is your job to write a review for that play.\n\nPlay Synopsis:\n{synopsis}\nReview from a New York Times play critic of the above play:"
prompt_template = PromptTemplate(input_variables=["synopsis"], template=review_template)
review_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="review")

overall_chain = SequentialChain(
    chains=[synopsis_chain, review_chain],
    input_variables=["era", "title"],
    output_variables=["synopsis", "review"],
    verbose=True,
)

overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})

在需要在整个链或链的后半部分保持上下文的场景中,可以使用 SimpleMemory。这在管理复杂的输入/输出关系时特别有用。例如,在一个需要根据戏剧的标题、时代、概要和评论生成社交媒体帖子的场景中,SimpleMemory 可以帮助管理这些变量:

from langchain.memory import SimpleMemory
from langchain.chains import SequentialChain

template = "You are a social media manager for a theater company. Given the title of play, the era it is set in, the date, time and location, the synopsis of the play, and the review of the play,it is your job to write a social media post for that play.\n\nHere is some context about the time and location of the play:\nDate and Time: {time}\nLocation: {location}\n\nPlay Synopsis:\n{synopsis}\nReview from a New York Times play critic of the above play:\n{review}\n\nSocial Media Post:"
prompt_template = PromptTemplate(input_variables=["synopsis", "review", "time", "location"], template=template)
social_chain = LLMChain(llm=llm, prompt=prompt_template, output_key="social_post_text")

overall_chain = SequentialChain(
    memory=SimpleMemory(memories={"time": "December 25th, 8pm PST", "location": "Theater in the Park"}),
    chains=[synopsis_chain, review_chain, social_chain],
    input_variables=["era", "title"],
    output_variables=["social_post_text"],
    verbose=True,
)

overall_chain({"title": "Tragedy at sunset on the beach", "era": "Victorian England"})

除了顺序链之外,还有一些专门用于处理文档的链。这些链各有不同的用途,从合并文档、基于迭代文档分析优化答案,到对文档内容进行映射和归纳以生成摘要或根据评分重新排序。这些链可以通过 LCEL 重新实现,从而提供更大的灵活性和定制能力。

  • StuffDocumentsChain:将文档列表合并为一个单一提示,传递给大型语言模型(LLM)。
  • RefineDocumentsChain:针对每个文档逐步更新答案,适用于文档超出模型上下文容量的任务。
  • MapReduceDocumentsChain:对每个文档单独应用链,然后合并结果。
  • MapRerankDocumentsChain:对基于文档的响应进行评分,并选择得分最高的结果。

以下是如何使用 LCEL 设置 MapReduceDocumentsChain 的示例:

from functools import partial
from langchain.chains.combine_documents import collapse_docs, split_list_of_docs
from langchain.schema import Document, StrOutputParser
from langchain.schema.prompt_template import format_document
from langchain.schema.runnable import RunnableParallel, RunnablePassthrough

llm = ChatAnthropic()
document_prompt = PromptTemplate.from_template("{page_content}")
partial_format_document = partial(format_document, prompt=document_prompt)

map_chain = (
    {"context": partial_format_document}
    | PromptTemplate.from_template("Summarize this content:\n\n{context}")
    | llm
    | StrOutputParser()
)

map_as_doc_chain = (
    RunnableParallel({"doc": RunnablePassthrough(), "content": map_chain})
    | (lambda x: Document(page_content=x["content"], metadata=x["doc"].metadata))
).with_config(run_name="Summarize (return doc)")

def format_docs(docs):
    return "\n\n".join(partial_format_document(doc) for doc in docs)

collapse_chain = (
    {"context": format_docs}
    | PromptTemplate.from_template("Collapse this content:\n\n{context}")
    | llm
    | StrOutputParser()
)

reduce_chain = (
    {"context": format_docs}
    | PromptTemplate.from_template("Combine these summaries:\n\n{context}")
    | llm
    | StrOutputParser()
).with_config(run_name="Reduce")

map_reduce = (map_as_doc_chain.map() | collapse | reduce_chain).with_config(run_name="Map reduce")

这种配置充分利用了 LCEL 和底层语言模型的优势,从而能够对文档内容进行详细而全面的分析。

<think>好的,用户想了解阿里云提供的机器学习服务或解决方案,特别是平台文档和示例。我需要根据提供的引用内容来整理回答。首先,我应该先概述阿里云机器学习平台PAI的基本情况,包括它的主要功能和优势,比如数据处理、建模、预测等,可能引用[1]和[2]。接下来,需要分点介绍核心功能,比如数据处理、模型训练、部署等,每个部分结合引用中的信息。然后,可以提到具体的应用案例或模型,比如PAI-Diffusion模型,引用[4],以及Whale框架,引用[5]。此外,文档和示例部分需要指出如何找到这些资源,可能引用[3]中的代码示例,或者PAI的官方文档。用户可能还关心如何快速上手,所以需要提供操作流程,引用[1]中的流程指导。最后,生成相关问题,帮助用户进一步探索。需要确保所有数学公式正确使用LaTeX格式,比如如果有提到算法中的公式,要用$$...$$。同时,检查引用标识是否正确对应,例如PAI EAS在引用[2],Whale在引用[5]。需要确保回答结构清晰,分步骤说明,并且真实可靠,引用相关的内容。最后生成的问题要覆盖用户可能想了解的更多方面,比如平台优势、应用场景、集成方法等。</think>阿里云机器学习平台(PAI)为企业与开发者提供全流程的AI解决方案,涵盖数据处理、模型训练、部署优化等环节。以下是其核心功能及文档示例的梳理: --- ### 一、PAI核心功能 1. **数据处理与准备** - 基于MaxCompute(原ODPS)构建,支持大规模数据清洗、特征工程,例如时序数据存储(如InfluxDB)与实时分析[^3]。 - **示例代码**(数据存储与调用): ```python # 调用阿里云SDK传输数据至PAI from aliyunsdkcore.client import AcsClient client = AcsClient(access_key_id, access_key_secret, region_id) # 将传感器数据存储至InfluxDB,并传输至PAI分析[^3] ``` 2. **模型开发与训练** - 支持主流框架(TensorFlow、PyTorch),提供预训练模型如PAI-Diffusion(中文艺术图像生成)[^4]。 - **高效训练框架**:Whale支持自动分布式优化,简化大模型训练流程[^5]。 3. **模型部署与调用** - **EAS(弹性算法服务)**:支持一键部署模型为RESTful API,集成Langchain等工具提升开发效率[^2]。 - **示例代码**(在线预测): ```python # 调用EAS部署的模型API import requests endpoint = "your_eas_endpoint" response = requests.post(endpoint, json={"input": "sample_data"}) ``` --- ### 二、文档与示例资源 1. **官方教程** - [PAI使用简明教程](引用[1]):详细指导数据准备、模型训练到部署的全流程。 2. **场景化案例** - **图像生成**:体验PAI-Diffusion生成高清艺术图[^4]。 - **物联网分析**:结合IoT平台与PAI实现传感器数据预测。 3. **开源项目** - Whale框架:GitHub开源仓库提供分布式训练代码示例[^5]。 --- ### 三、快速入门流程 1. **数据准备**:上传数据至MaxCompute,完成预处理。 2. **模型构建**:通过PAI Studio拖拽式建模或代码开发。 3. **部署与调用**:通过EAS发布API,集成至业务系统。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CS创新实验室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值