组件#

Component 对于LLM任务管道来说,就像 nn.Module 对于PyTorch模型一样。 它是LightRAG中诸如 PromptModelClientGeneratorRetriever 等组件的基础类。 你的任务管道也应该从 Component 继承。

设计#

与PyTorch的nn.Module不同,它仅与Tensor和Parameter一起工作,用于训练具有权重和偏置的模型,我们的组件可以与不同类型的数据一起工作,从字符串或字符串列表到Document列表。

这是编写PyTorch模型和LightRAG任务管道的比较。

PyTorch
import torch.nn as nn
import torch.nn.functional as F

class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))
AdalFlow
from adalflow.core import Component, Generator
from adalflow.components.model_client import OpenAIClient


template_doc = r"""<SYS> You are a doctor </SYS> User: {{input_str}}"""

class DocQA(Component):
    def __init__(self):
        super().__init__()
        self.doc = Generator(
            template=template_doc,
            model_client=OpenAIClient(),
            model_kwargs={"model": "gpt-3.5-turbo"},
        )

    def call(self, query: str) -> str:
        return self.doc(prompt_kwargs={"input_str": query}).data

作为LLM任务管道中的基本构建块,该组件旨在服务于五个主要目的:

  1. 标准化所有组件的接口。 这包括__init__方法、用于同步调用的call方法、用于异步调用的acall方法,以及默认调用call方法的__call__方法。

  2. 提供一种统一的方式来可视化任务管道的结构 通过__repr__方法。子类可以额外添加_extra_repr方法,以包含比默认__repr__方法更多的信息。

  3. 自动递归地跟踪和添加所有子组件和参数 以协助任务管道的构建和优化过程。

  4. 管理状态和序列化, 使用state_dictload_state_dict方法专门用于参数,以及to_dict方法用于序列化组件属性中的所有状态,从子组件到参数,再到各种数据类型的任何其他属性。

  5. 使用 `json` 或 `yaml` 文件使所有组件可配置。 这对于实验或构建数据处理管道特别有用。

这些特性是保持LightRAG管道透明、灵活和易于使用的关键。 通过从Component类继承,您将获得大部分这些开箱即用的特性。

组件在行动中#

在这篇笔记中,我们正在创建一个AI医生来回答医疗问题。 在查询上运行DocQA

doc = DocQA()
print(doc("What is the best treatment for headache?"))

响应是:

As a doctor, the best treatment for a headache would depend on the underlying cause of the headache. Typically, over-the-counter pain relievers such as acetaminophen, ibuprofen, or aspirin can help to alleviate the pain. However, if the headache is severe or persistent, it is important to see a doctor for further evaluation and to determine the most appropriate treatment option. Other treatment options may include prescription medications, lifestyle modifications, stress management techniques, and relaxation techniques.

从文件配置#

如上例所示,我们通过属性添加了子组件。 我们还可以使用方法来添加更多的子组件或参数。

from adalflow.core.parameter import Parameter

doc.register_parameter("demo", param=Parameter(data="demo"))
# list all parameters
for param in doc.named_parameters():
    print(param)

输出:

('demo', Parameter: demo)

您可以轻松保存详细状态:

from utils.file_io import save_json

save_json(doc.to_dict(), "doc.json")

为了增加更多的灵活性,我们提供了FunComponentSequential用于更高级的用例。

序列化和反序列化#

我们提供了is_pickable方法来检查组件是否可拾取。 确保您的任何组件都是可拾取的是一个好的做法。

FunComponent#

使用fun_to_component作为装饰器,将任何函数转换为具有其唯一类名的组件。

FunComponentComponent 的一个子类,允许你使用函数定义一个组件。 你可以直接使用这个类,如下所示:

from adalflow.core.component import FunComponent

def add_one(x):
    return x + 1

fun_component = FunComponent(add_one)
print(fun_component(1))
print(type(fun_component))

打印输出:

2
<class 'core.component.FunComponent'>

我们还有fun_to_component,可以通过装饰器或直接调用函数将函数转换为FunComponent。 这种方法为您提供了一个从函数名称转换而来的独特组件。

通过直接调用:

from adalflow.core.component import fun_to_component

fun_component = fun_to_component(add_one)
print(fun_component(1))
print(type(fun_component))

输出:

2
<class 'adalflow.core.component.AddOneComponent'>

使用装饰器是从函数创建组件的一种更为便捷的方式:

@fun_to_component
def add_one(x):
    return x + 1

print(add_one(1))
print(type(add_one))

# output:
# 2
# <class 'adalflow.core.component.AddOneComponent'>

顺序#

我们有Sequential类,它类似于PyTorch的nn.Sequential类。 这对于将组件按顺序链接在一起特别有用,就像其他LLM库中的chainpipeline概念一样。 让我们将FunComponent`DocQA`按顺序放在一起:

from adalflow.core.container import Sequential

@fun_to_component
def enhance_query(query:str) -> str:
    return query + "Please be concise and only list the top treatments."

seq = Sequential(enhance_query, doc)

query = "What is the best treatment for headache?"
print(seq(query))

在将用户的查询传递给DocQA组件之前,我们会自动增强这些查询。 输出结果是:

1. Over-the-counter pain relievers like acetaminophen, ibuprofen, or aspirin
2. Rest and relaxation
3. Stay hydrated and drink plenty of water

使用print(seq)的序列结构:

Sequential(
(0): EnhanceQueryComponent()
(1): DocQA(
        (doc): Generator(
        model_kwargs={'model': 'gpt-3.5-turbo'}, model_type=ModelType.LLM
        (prompt): Prompt(template: <SYS> You are a doctor </SYS> User: {{input_str}}, prompt_variables: ['input_str'])
        (model_client): OpenAIClient()
        )
    )
)

我们将在接下来的教程中介绍更高级的用例。