Langchain文档 连接特征存储

359 阅读5分钟

特征存储

特征存储是传统机器学习中的一个概念,它确保输入模型的数据是最新和相关的。要了解更多信息,请参阅此处。在考虑将LLM应用程序投入生产时,这个概念非常重要。为了个性化LLM应用程序,您可能希望将LLM与特定用户的最新信息结合起来。特征存储可以是保持数据新鲜的一种很好的方式,而LangChain则提供了一种将数据与LLM结合在一起的简单方法。

在本笔记本中,我们将展示如何将提示模板与特征存储连接起来。基本思想是从提示模板内部调用特征存储以检索值,然后将这些值格式化到提示中。

Feast

首先,我们将使用流行的开源特征存储框架Feast。这假设您已经按照README中的步骤进行了设置。我们将在此基础上构建,并创建一个LLMChain来向特定驾驶员写一封关于他们最新统计数据的便笺。

加载Feast存储

再次强调,这应根据Feast README中的说明进行设置

from feast import FeatureStore

# 根据您的存储位置进行更新
feast_repo_path = "../../../../../my_feature_repo/feature_repo/"

store = FeatureStore(repo_path=feast_repo_path)

提示

在这里,我们将设置一个自定义的FeastPromptTemplate。此提示模板将接收驾驶员ID,查找其统计数据,并将这些统计数据格式化到提示中。

请注意,此提示模板的输入仅为driver_id,因为这是仅由用户定义的部分(所有其他变量都在提示模板内部查找)。

from langchain.prompts import PromptTemplate, StringPromptTemplate

template = """
给驾驶员的最新统计数据,写一封便条向他们传达这些统计数据。
如果他们的转化率超过0.5,请称赞他们。
否则,在最后加上一个关于鸡的愚蠢玩笑,让他们感觉更好。

以下是驾驶员的统计数据:
转化率:{conv_rate}
接受率:{acc_rate}
平均每日行程数:{avg_daily_trips}

请回复:
"""

prompt = PromptTemplate.from_template(template)

class FeastPromptTemplate(StringPromptTemplate):
    def format(self, **kwargs) -> str:
        driver_id = kwargs.pop("driver_id")
        feature_vector = store.get_online_features(
            features=[
                "driver_hourly_stats:conv_rate",
                "driver_hourly_stats:acc_rate",
                "driver_hourly_stats:avg_daily_trips",
            ],
            entity_rows=[{"driver_id": driver_id}],
        ).to_dict()
        kwargs["conv_rate"] = feature_vector["conv_rate"][0]
        kwargs["acc_rate"] = feature_vector["acc_rate"][0]
        kwargs["avg_daily_trips"] = feature_vector["avg_daily_trips"][0]
        return prompt.format(**kwargs)

prompt_template = FeastPromptTemplate(input_variables=["driver_id"])

print(prompt_template.format(driver_id=1001))

链式使用

现在我们可以在链式中使用它,成功创建一个由特征存储支持的链式。

from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain

chain = LLMChain(llm=ChatOpenAI(), prompt=prompt_template)

chain.run("user_469998441571")

Tecton

上面,我们展示了如何使用Feast与LangChain进行集成。下面的示例将展示使用Tecton进行类似集成。Tecton是一个完全托管的特征平台,用于协调完整的ML特征生命周期,从转换到在线服务,并提供企业级SLA。

先决条件

  • Tecton部署(请在tecton.ai上注册)
  • 设置TECTON_API_KEY环境变量为有效的Service Account密钥

定义和加载特征

我们将使用Tecton教程中的user_transaction_counts Feature View作为Feature Service的一部分。为了简单起见,我们只使用一个Feature View;然而,更复杂的应用可能需要更多的特征视图来检索其提示所需的特征。

import tecton

workspace = tecton.get_workspace("prod")
feature_service = workspace.get_feature_service("user_transaction_metrics")

提示

在这里,我们将设置一个自定义的TectonPromptTemplate。此提示模板将接收用户ID,查找其统计数据,并将这些统计数据格式化到提示中。

请注意,此提示模板的输入仅为user_id,因为这是仅由用户定义的部分(所有其他变量都在提示模板内部查找)。

from langchain.prompts import PromptTemplate, StringPromptTemplate

template = """
给供应商的最新交易统计数据,根据以下规则写一封便条:
1. 如果他们在过去一天内有交易,请在他们的最近销售上写一封简短的祝贺信息。
2. 如果过去一天没有交易,但过去30天内有交易,请开玩笑地鼓励他们多销售一些。
3. 最后,加上一个关于鸡的愚蠢玩笑。

以下是供应商的统计数据:
过去一天的交易数:{transaction_count_1d}
过去30天的交易数:{transaction_count_30d}

请回复:
"""

prompt = PromptTemplate.from_template(template)

class TectonPromptTemplate(StringPromptTemplate):
    def format(self, **kwargs) -> str:
        user_id = kwargs.pop("user_id")
        feature_vector = feature_service.get_online_features(
            join_keys={"user_id": user_id}
        ).to_dict()
        kwargs["transaction_count_1d"] = feature_vector[
            "user_transaction_counts.transaction_count_1d_1d"
        ]
        kwargs["transaction_count_30d"] = feature_vector[
            "user_transaction_counts.transaction_count_30d_1d"
        ]
        return prompt.format(**kwargs)

prompt_template = TectonPromptTemplate(input_variables=["user_id"])

print(prompt_template.format(user_id="user_469998441571"))

链式使用

现在我们可以在链式中使用它,成功创建一个由Tecton Feature平台支持的链式。

from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain

chain = LLMChain(llm=ChatOpenAI(), prompt=prompt_template)

chain.run("user_469998441571")

Featureform

最后,我们将使用Featureform作为开源的企业级特征存储来运行相同的示例。Featureform允许您使用Spark或本地等基础设施来定义特征转换,并对其进行操作。

初始化Featureform

您可以按照README中的说明初始化Featureform的转换和特征。

import featureform as ff

client = ff.Client(host="demo.featureform.com")

提示

在这里,我们将设置一个自定义的FeatureformPromptTemplate。此提示模板将接收用户平均每个交易支付的金额。

请注意,此提示模板的输入仅为avg_transaction,因为这是仅由用户定义的部分(所有其他变量都在提示模板内部查找)。

from langchain.prompts import PromptTemplate, StringPromptTemplate

template = """
给用户平均每个交易支付的金额,让他们知道他们是否是高额赌徒。否则,在最后加上一个关于鸡的愚蠢玩笑,让他们感觉更好。

以下是用户的统计数据:
每个交易的平均金额:${avg_transaction}

请回复:
"""

prompt = PromptTemplate.from_template(template)

class FeatureformPromptTemplate(StringPromptTemplate):
    def format(self, **kwargs) -> str:
        user_id = kwargs.pop("user_id")
        fpf = client.features([("avg_transactions", "quickstart")], {"user": user_id})
        return prompt.format(**kwargs)

prompt_template = FeatureformPromptTemplate(input_variables=["user_id"])

print(prompt_template.format(user_id="C1410926"))

链式使用

现在我们可以在链式中使用它,成功创建一个由Featureform Feature平台支持的链式。

from langchain.chat_models import ChatOpenAI
from langchain.chains import LLMChain

chain = LLMChain(llm=ChatOpenAI(), prompt=prompt_template)