特征存储
特征存储是传统机器学习中的一个概念,它确保输入模型的数据是最新和相关的。要了解更多信息,请参阅此处。在考虑将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)