前言
官方文档:链(Chains)
做一件事需要很多个步骤,而每一个步骤都是问题处理流程上的节点。将这些节点串联或并联起来就形成了解决问题的“链”。
对于简单问题,通常一个节点即可完成,而一旦涉及到复杂问题处理,则需要连接各种各样的链了。
一点尝试
我们沿用上一节的模板测试,同样的模板内容,除了直接复制文字进行提问外,还可以使用封装好的模板,通过chain来调用
import include
from langchain.chat_models import ChatOpenAI
from langchain import LLMChain
from langchain.chains.retrieval_qa.prompt import PROMPT
# 使用的模型
chat = ChatOpenAI(
model="gpt-35-turbo",
model_kwargs={"deployment_id": "gpt-35-turbo"},
temperature=0.5
)
# 给出的context
context = """
充值金额 charge_money
退款金额 refund_money
广告费 ad_money
充值人数 charge_people
登陆人数 login_people
"""
# 创建链,这里的prompt使用了langchain包里自带的QA模板,在第一节学习笔记中有贴出来过内容
chain = LLMChain(llm=chat, prompt=PROMPT)
# 模板里有变量占位符question和context,所以这里指定这两个参数
rs = chain.run(question="和金额有关的指标有哪些?", context=context)
print(rs)
充值金额、退款金额、广告费。
Process finished with exit code 0
这样就完成了一个最简单的chain。
做一个自己的链
步骤一
接着上一节,对语言识别成指标的prompt也做一点改造,功能是:解析自然语言,转换为对应格式Json
import include
from langchain import LLMChain, PromptTemplate
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(
model="gpt-35-turbo",
model_kwargs={"deployment_id": "gpt-35-turbo"},
temperature=0,
)
# 示例
example = """
example:
Sentence:星穹铁道2022年8月充值金额、退款金额、广告费,按天、渠道
Result:
{
"metas": ["充值金额", "退款金额", "广告费"],
"dims": ["天", "渠道"],
"filters": {"游戏":"凡人修仙传", "时间":"2022年8月"}
}
"""
# 模板内容,使用了format_instructions和question占位符
template = """Recognize all the meta names, dimension names, and filters in the given sentence, return them in json format.
{format_instructions}
Sentence: {question}
Result:"""
# 限定模板接收的输入question,对format_instructions使用示例example填充
prompt_template = PromptTemplate(
input_variables=["question"],
partial_variables={"format_instructions": example},
template=template,
)
# verbose开启调试日志
split_chain = LLMChain(llm=llm, prompt=prompt_template, verbose=True)
result = split_chain.run("凡人修仙传2023年上半年的广告费、渠道费、税费,按自然月、平台、服务器")
print(result)
给出了链的完整处理流程和对话内容
> Entering new LLMChain chain...
Prompt after formatting:
Recognize all the meta names, dimension names, and filters in the given sentence, return them in json format.
example:
Sentence:星穹铁道2022年8月充值金额、退款金额、广告费,按天、渠道
Result:
{
"metas": ["充值金额", "退款金额", "广告费"],
"dims": ["天", "渠道"],
"filters": {"游戏":"凡人修仙传", "时间":"2022年8月"}
}
Sentence: 凡人修仙传2023年上半年的广告费、渠道费、税费,按自然月、平台、服务器
Result:
> Finished chain.
{
"metas": ["广告费", "渠道费", "税费"],
"dims": ["自然月", "平台", "服务器"],
"filters": {"游戏":"凡人修仙传", "时间":"2023年上半年"}
}
Process finished with exit code 0
步骤二
对自然语言形成的Json做转码,换成我们自己定义的内容。
import include
from langchain import LLMChain, PromptTemplate
from langchain.chat_models import ChatOpenAI
llm = ChatOpenAI(
model="gpt-35-turbo",
model_kwargs={"deployment_id": "gpt-35-turbo"},
temperature=0,
)
# 这里预先给出一些指标和维度的定义,并告诉AI要换掉他们,时间也要换成start_date和end_date
template = """Use the following pieces of context, convert mata and dimension and filter names to code. Convert the filters '时间' into start_date and end_date.
指标:
充值金额 charge_money
退款金额 refund_money
广告费 ad_fee
渠道费 channel_fee
税费 tax_fee
维度:
自然月 month
天 day
游戏 game
平台 platform
服务器 server
{format_instructions}
{inputs}
Result:"""
example = """
example:
{
"metas": ["充值金额", "退款金额"],
"dims": ["天"],
"filters": {"时间":"2023年","游戏":"109,110"}
}
Result:
{
"metas": ["charge_money", "refund_money"],
"dims": ["day"],
"filters": {"start_date":"2023-01-01 00:00:00", "end_date":"2023-12-31 23:59:59", "game": "109,110"}
}
"""
prompt_template = PromptTemplate(
input_variables=["inputs"],
partial_variables={"format_instructions": example},
template=template,
)
convert_chain = LLMChain(llm=llm, prompt=prompt_template, verbose=True)
question = """
{
"metas": ["广告费", "渠道费", "税费"],
"dims": ["自然月", "平台", "服务器"],
"filters": {"游戏":"凡人修仙传", "时间":"2023年上半年"}
}
"""
result = convert_chain.run(question)
print(result)
运行结果
> Entering new LLMChain chain...
Prompt after formatting:
Use the following pieces of context, convert mata and dimension and filter names to code. Convert the filters '时间' into start_date and end_date.
指标:
充值金额 charge_money
退款金额 refund_money
广告费 ad_fee
渠道费 channel_fee
税费 tax_fee
维度:
自然月 month
天 day
游戏 game
平台 platform
服务器 server
example:
{
"metas": ["充值金额", "退款金额"],
"dims": ["天"],
"filters": {"时间":"2023年","游戏":"109,110"}
}
Result:
{
"metas": ["charge_money", "refund_money"],
"dims": ["day"],
"filters": {"start_date":"2023-01-01 00:00:00", "end_date":"2023-12-31 23:59:59", "game": "109,110"}
}
{
"metas": ["广告费", "渠道费", "税费"],
"dims": ["自然月", "平台", "服务器"],
"filters": {"游戏":"凡人修仙传", "时间":"2023年上半年"}
}
Result:
> Finished chain.
{
"metas": ["ad_fee", "channel_fee", "tax_fee"],
"dims": ["month", "platform", "server"],
"filters": {"start_date":"2023-01-01 00:00:00", "end_date":"2023-06-30 23:59:59", "game": "凡人修仙传"}
}
Process finished with exit code 0
步骤三
将前面两个链串起来,这里使用LangChain提供的顺序链
from langchain.chains import SimpleSequentialChain
# 这里的split_chain和convert_chain就是上面两段示例中的同名变量链,这里就不再复制一遍代码了
overall_chain = SimpleSequentialChain(chains=[split_chain, convert_chain], verbose=True)
result = overall_chain.run("凡人修仙传2023年上半年的广告费、渠道费、税费,按自然月、平台、服务器")
print(result)
运行结果,将两个链条中的处理流程串起来了,前一个链的输出成为了后一个链的输入。
> Entering new SimpleSequentialChain chain...
> Entering new LLMChain chain...
Prompt after formatting:
Recognize all the meta names, dimension names, and filters in the given sentence, return them in json format.
example:
Sentence:星穹铁道2022年8月充值金额、退款金额、广告费,按天、渠道
Result:
{
"metas": ["充值金额", "退款金额", "广告费"],
"dims": ["天", "渠道"],
"filters": {"游戏":"凡人修仙传", "时间":"2022年8月"}
}
Sentence: 凡人修仙传2023年上半年的广告费、渠道费、税费,按自然月、平台、服务器
Result:
> Finished chain.
{
"metas": ["广告费", "渠道费", "税费"],
"dims": ["自然月", "平台", "服务器"],
"filters": {"游戏":"凡人修仙传", "时间":"2023年上半年"}
}
> Entering new LLMChain chain...
Prompt after formatting:
Use the following pieces of context, convert mata and dimension and filter names to code. Convert the filters '时间' into start_date and end_date.
指标:
充值金额 charge_money
退款金额 refund_money
广告费 ad_fee
渠道费 channel_fee
税费 tax_fee
维度:
自然月 month
天 day
游戏 game
平台 platform
服务器 server
example:
{
"metas": ["充值金额", "退款金额"],
"dims": ["天"],
"filters": {"时间":"2023年","游戏":"109,110"}
}
Result:
{
"metas": ["charge_money", "refund_money"],
"dims": ["day"],
"filters": {"start_date":"2023-01-01 00:00:00", "end_date":"2023-12-31 23:59:59", "game": "109,110"}
}
{
"metas": ["广告费", "渠道费", "税费"],
"dims": ["自然月", "平台", "服务器"],
"filters": {"游戏":"凡人修仙传", "时间":"2023年上半年"}
}
Result:
> Finished chain.
{
"metas": ["ad_fee", "channel_fee", "tax_fee"],
"dims": ["month", "platform", "server"],
"filters": {"start_date":"2023-01-01 00:00:00", "end_date":"2023-06-30 23:59:59", "game": "凡人修仙传"}
}
> Finished chain.
{
"metas": ["ad_fee", "channel_fee", "tax_fee"],
"dims": ["month", "platform", "server"],
"filters": {"start_date":"2023-01-01 00:00:00", "end_date":"2023-06-30 23:59:59", "game": "凡人修仙传"}
}
Process finished with exit code 0
步骤四
到这里就完成了一个简单的链的组装,后续只需要调用步骤三里的overall_chain就可以得到最后格式化的Json了。
但还有一些问题没有处理。
- 第二条链里提示的指标数太少,而一旦提供全量指标,可能会超出对话Token限制
- 自然语言识别成Json的Prompts显然还需要调优,以兼容更多对话方式
- 我们解析出来Json要怎么使用呢?或许还需要用到LangChain的Tools
PS.
链的调用、组装方式还有很多很多,我目前也仅仅是使用了一点皮毛,更多用户还请参考官方文档: 链 Chains。
里面有诸如:
异步链
内容审查链
数学链
路由链-提示
路由链-问答
……