LLm_React

Posted on 5月 5, 2024

LLM 缺陷

尽管大型语言模型(LLMs)在语言理解任务(如QA)和交互式决策制定(如 Function calling)中展示了令人印象深刻的能力,但它们在推理(例如,思维链提示)和行动(例如,行动计划生成)方面的能力主要是作为独立主题进行研究的1

思维链/行动 —> 思维链+行动 React

LLM_React

通过交错 生成推理轨迹进行特定任务行动 的方式协同作用,能够克服通过思维链推理普遍存在的幻觉和错误传播问题且优于模仿和强化学习方法。

生成推理轨迹

帮助模型进行 诱导 跟踪 更新行动计划 处理异常
-> 诱导 烹饪一道番茄炒蛋需要哪些材料 有哪些步骤
-> 跟踪 既然材料准备好了,要准备热锅放油了
-> 处理异常 盐不够用了,所以需要使用其他调味料代替
-> 更新行动计划 使用酱油代替盐进行烹饪

特定任务行动

与外部来源(例如知识库、环境) 交互并收集附加信息
-> 行动 打开菜谱 检查食材是否满足

React 类似人类解决问题 通过面向任务的 内心言语(思考 内心对白) 生成行动计划 并进行 特定子任务 行动 当出现异常时对计划进行修正

“行动”和“推理”之间的这种紧密协同作用使人类能够快速学习新任务并执行稳健的决策或推理,即使是在以前未见过的情况下或面临信息不确定性。

论文Code的 LLM_React 实现

hotpotqa.ipynb2

Prompt指令

解决一个问答任务,通过交错思考、行动、观察步骤。思考可以对当前情况做出推理,而行动可以是三种类型:
(1)搜索[实体],它在维基百科上搜索确切的实体,并在存在的情况下返回第一段。如果不存在,它将返回一些相似的实体进行搜索。
(2)查找[关键词],它返回当前段落中包含关键词的下一句话。
(3)完成[答案],它返回答案并完成任务。
这里有一些例子。

Prompt示例

通过多轮 思考->行动->观察 解决任务

问题:科罗拉多造山带东部地区延伸到的区域海拔范围是多少?

思考1:我需要搜索科罗拉多造山带,找到科罗拉多造山带东部地区延伸到的区域,然后找到该区域的海拔范围。
行动1:搜索[科罗拉多造山带]
观察1:科罗拉多造山带是科罗拉多州及周边地区发生的一次造山运动(造山带)。

思考2:它没有提到东部地区。所以我需要查找东部地区。
行动2:查找[东部地区]
观察2:(结果1/1)东部地区延伸到高平原,被称为中部平原造山带。

思考3:科罗拉多造山带的东部地区延伸到高平原。所以我需要搜索高平原并找到它的海拔范围。
行动3:搜索[高平原]
观察3:高平原指的是两个不同地区之一:

思考4:我需要改为搜索高平原(美国)。
行动4:搜索[高平原(美国)]
观察4:高平原是大平原的一个子区域。从东到西,高平原的海拔从大约1,800英尺上升到7,000英尺(550到2,130米)。

思考5:高平原的海拔从大约1,800英尺上升到7,000英尺,所以答案是1,800到7,000英尺。
行动5:完成[1,800到7,000英尺]


问题:音乐家和讽刺家Allie Goertz写了一首关于《辛普森一家》角色米尔豪斯的歌,马特·格罗宁以谁的名字命名了米尔豪斯?
思考1:问题简化为《辛普森一家》角色米尔豪斯是以谁的名字命名的。我只需要搜索米尔豪斯并找出它是以谁的名字命名的。
行动1:搜索[米尔豪斯]
观察1:米尔豪斯·穆索里尼·范霍顿是福克斯动画电视系列《辛普森一家》中的一个反复出现的角色,由帕梅拉·海登配音,由马特·格罗宁创造。

思考2:段落没有告诉我们米尔豪斯是以谁的名字命名的,也许我可以查找“以...命名”。
行动2:查找[以...命名]
观察2:(结果1/1)米尔豪斯是以美国总统理查德·尼克松的名字命名的,他的中间名是米尔豪斯。

思考3:米尔豪斯是以美国总统理查德·尼克松的名字命名的,所以答案是理查德·尼克松。
行动3:完成[理查德·尼克松]

问题:关于芬兰摇滚乐队的纪录片是亚当·克莱顿·鲍威尔还是《塞马湖的手势》?
思考1:我需要搜索亚当·克莱顿·鲍威尔和《塞马湖的手势》,找出哪部纪录片是关于芬兰摇滚乐队的。
行动1:搜索[亚当·克莱顿·鲍威尔]
观察1:未能找到[亚当·克莱顿·鲍威尔]。相似的:[亚当·克莱顿·鲍威尔三世,第七大道(曼哈顿),亚当·克莱顿·鲍威尔州办公大楼,伊莎贝尔·华盛顿·鲍威尔,亚当·鲍威尔,亚当·克莱顿·鲍威尔(电影),詹卡洛·埃斯波西托]。

思考2:为了找到纪录片,我可以搜索亚当·克莱顿·鲍威尔(电影)。
行动2:搜索[亚当·克莱顿·鲍威尔(电影)]
观察2:亚当·克莱顿·鲍威尔是一部1989年的美国纪录片,由理查德·基尔伯格执导。
这部电影是关于有影响力的非裔美国政治家亚当·克莱顿·鲍威尔二世的兴衰。[3][4] 它后来作为PBS系列《美国经历》的一部分播出。

思考3:亚当·克莱顿·鲍威尔(电影)是一部关于非裔美国政治家的纪录片,而不是芬兰摇滚乐队。所以关于芬兰摇滚乐队的纪录片一定是《塞马湖的手势》。
行动3:完成[《塞马湖的手势》]

问题:尼古拉斯·雷和埃利亚·卡赞有什么共同的职业?

思考1:我需要搜索尼古拉斯·雷和埃利亚·卡赞,找到他们的职业,然后找出他们共同的职业。
行动1:搜索[尼古拉斯·雷]
观察1:尼古拉斯·雷(本名雷蒙德·尼古拉斯·基恩兹尔二世,1911年8月7日 - 1979年6月16日)是美国人,电影导演、编剧和演员,以1955年的电影《无因的反叛》最为人所知。

思考2:尼古拉斯·雷的职业是导演、编剧和演员。我接下来需要搜索埃利亚·卡赞并找到他的职业。
行动2:搜索[埃利亚·卡赞]
观察2:埃利亚·卡赞是美国人,电影和戏剧导演、制片人、编剧和演员。

思考3:埃利亚·卡赞的职业是导演、制片人、编剧和演员。所以尼古拉斯·雷和埃利亚·卡赞共同的职业是导演、编剧和演员。
行动3:完成[导演,编剧,演员]


问题:《亚瑟杂志》和《妇女第一》哪个杂志先开始的?

思考1:我需要搜索《亚瑟杂志》和《妇女第一》,找出哪个杂志先开始的。
行动1:搜索[《亚瑟杂志》]
观察1:《亚瑟杂志》(1844-1846)是19世纪在费城出版的美国文学期刊。

思考2:《亚瑟杂志》始于1844年。我接下来需要搜索《妇女第一》。
行动2:搜索[《妇女第一》]
观察2:《妇女第一》是由美国鲍尔媒体集团出版的女性杂志。[1] 该杂志始于1989年。

思考3:《妇女第一》始于1989年。1844年(《亚瑟杂志》)< 1989年(《妇女第一》),所以《亚瑟杂志》是先开始的。
行动3:完成[《亚瑟杂志》]


问题:帕维尔·乌里索恩和列昂尼德·列文是否因同类型的工作而闻名?
思考1:我需要搜索帕维尔·乌里索恩和列昂尼德·列文,找到他们的工作类型,然后找出它们是否相同。
行动1:搜索[帕维尔·乌里索恩]
观察1:帕维尔·萨穆伊洛维奇·乌里索恩(1898年2月3日 - 1924年8月17日)是苏联数学家,以其在维数理论方面的贡献而闻名。

思考2:帕维尔·乌里索恩是数学家。我接下来需要搜索列昂尼德·列文并找到他的工作类型。
行动2:搜索[列昂尼德·列文]
观察2:列昂尼德·阿纳托利耶维奇·列文是苏联-美国数学家和计算机科学家。

思考3:列昂尼德·列文是数学家和计算机科学家。所以帕维尔·乌里索恩和列昂尼德·列文有相同的工作类型。
行动3:完成[是]

Task

    prompt =  指令 + 示例
    prompt += question + "\n" # 拼接问题构造完整的prompt
    n_calls, n_badcalls = 0, 0 # 统计调用次数和错误次数
    for i in range(1, 8):
        n_calls += 1
        thought_action = llm(prompt + f"思考 {i}:", stop=[f"\n观察 {i}:"]) # 生成思考 和 行动 
        try:
            thought, action = thought_action.strip().split(f"\n行动 {i}: ") # 获取 思考 和 行动
        except:
            n_badcalls += 1
            n_calls += 1
            thought = thought_action.strip().split('\n')[0] # 没有行动 提取思考内容
            action = llm(prompt + f"思考 {i}: {thought}\nAction {i}:", stop=[f"\n"]).strip() #使用思考,生成行动
        obs, r, done, info = step(env, action[0].lower() + action[1:]) # 进行行动 ,获取结果 将Action首字母小写 
        obs = obs.replace('\\n', '')
        step_str = f"思考 {i}: {thought}\nAction {i}: {action}\nObservation {i}: {obs}\n" # 拼接思考,行动,结果
        prompt += step_str
        if done: # 如果行动完成
            break
    if not done:
    obs, r, done, info = step(env, "finish[]") # 结束行动
    info.update({'n_calls': n_calls, 'n_badcalls': n_badcalls, 'traj': prompt}) # 记录调用次数 和 错误次数 以及轨迹
    return r, info

Langchain 中的 LLM_React 实现3

Prompt指令4

问题:请尽可能好地回答以下问题。您可以使用以下工具:
{工具}
请使用以下格式:
问题:您必须回答的输入问题
思考:您应该始终思考要做什么
行动:要采取的行动,应该是[{工具名称列表}]之一
行动输入:行动的输入
观察:行动的结果
...(这个思考/行动/行动输入/观察可以重复N次)
思考:我现在知道最终答案了
最终答案:原始输入问题的最终答案
开始!
问题:{输入}
思考:{代理便签}

执行示例

问题: 什么是LangChain?

> 正在进入新的AgentExecutor链...
我需要研究LangChain以了解更多信息。

动作:tavily_search_results_json
动作输入:“LangChain”[{'url': 'https://www.ibm.com/topics/langchain', 'content': 'LangChain本质上是Python和Javascript的一个抽象库,代表了常见的步骤和概念。LangChain是一个开源的编排框架,用于开发使用大型语言模型的应用程序。LangChain的其他特性,如同名的链条。LangChain为超过25种不同的嵌入方法以及超过50种不同的向量存储提供了集成。LangChain是一个使用大型语言模型(LLMs)构建应用程序的工具,例如聊天机器人和虚拟代理。它简化了编程和与外部数据源及软件工作流程的集成过程。它支持Python和Javascript语言,并支持各种LLM提供商,包括OpenAI、Google和IBM。'}] 我应该阅读摘要,并查看LangChain的不同特性和集成。

动作:tavily_search_results_json
动作输入:“LangChain特性和集成”[{'url': 'https://www.ibm.com/topics/langchain', 'content': "LangChain为超过25种不同的嵌入方法以及超过50种不同的向量存储提供了集成。LangChain是一个开源的编排框架,用于开发使用大型语言模型的应用程序。LangChain的其他特性,如同名的链条。LangChain本质上是Python和Javascript的一个抽象库,代表了常见的步骤和概念。由Harrison Chase在2022年10月启动,LangChain迅速崛起并广受欢迎:截至2023年6月,它已成为GitHub上增长最快的开源项目。与OpenAI的ChatGPT在下个月的重要发布相吻合,LangChain在使生成性AI更加易于访问方面发挥了重要作用..."}] 我应该记下LangChain的发布日期和受欢迎程度。
动作:tavily_search_results_json

动作输入:“LangChain发布日期和受欢迎程度”[{'url': 'https://www.ibm.com/topics/langchain', 'content': "LangChain是一个开源的编排框架,用于开发使用大型语言模型的应用程序。LangChain的其他特性,如同名的链条。LangChain为超过25种不同的嵌入方法以及超过50种不同的向量存储提供了集成。LangChain本质上是Python和Javascript的一个抽象库,代表了常见的步骤和概念。由Harrison Chase在2022年10月启动,LangChain迅速崛起并广受欢迎:截至2023年6月,它已成为GitHub上增长最快的开源项目。与OpenAI的ChatGPT在下个月的重要发布相吻合,LangChain在使生成性AI更加易于访问方面发挥了重要作用..."}] 现在我知道最终答案了。

最终答案:LangChain是一个开源的编排框架,用于构建使用大型语言模型(LLMs)的应用程序,如聊天机器人和虚拟代理。它由Harrison Chase在2022年10月启动,并在2023年6月成为GitHub上增长最快的开源项目,广受欢迎。
> 链已完成。

Code

from langchain import hub
from langchain.agents import AgentExecutor, create_react_agent
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import OpenAI

tools = [TavilySearchResults(max_results=1)] # 加载工具

prompt = hub.pull("hwchase17/react") # 从hub中加载prompt

llm = OpenAI()

agent = create_react_agent(llm, tools, prompt) # 生成 React agent

agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True) # 创建Agent 执行器 传入Agent 和 工具  并打印详细信息
agent_executor.invoke({"input": "what is LangChain?"}) # 执行agent

dify 中的 LLM_React 实现

在Dify 中文本生成与Chat 作为两种不同类型的应用 使用了不同的Prompt指令5

文本生成

文本生成Prompt指令

回答人类的问题时尽可能地提供帮助和准确信息。
{{指令}}
你可以使用以下工具:
{{工具}}
使用json块来指定工具,提供动作键(工具名称)和动作输入键(工具输入)。
有效的“动作”值:“Final Answer”或{{工具名称}}
每个$JSON_BLOB只能提供一项动作,如示例所示:
```
{
"action": $工具名称,
"action_input": $动作输入
}
```
请按照以下格式:
问题:输入要回答的问题
思考:考虑之前的和后续的步骤
动作:
```
$JSON块
```
观察:动作结果
...(重复思考/动作/观察N次)
思考:我知道如何回应
动作:
```
{
"action": "Final Answer",
"action_input": "对人类的最终回应"
}
```
开始!提醒总是以单个动作的有效json块回应。必要时使用工具。如果合适,直接回应。格式是动作:```$JSON块```然后观察:。
{{历史消息}}
问题:{{查询}}
{{代理便笺}}
思考:

Chat

Chat Prompt指令

回答人类的问题要尽可能地有帮助和准确。
{{指令}}
你可以使用以下工具:
{{工具}}
使用json blob通过提供动作键(工具名称)和动作输入键(工具输入)来指定一个工具。
有效的"action"值:"Final Answer"或{{tool_names}}
每个$JSON_BLOB只能提供一次动作,如下所示:
```
{
"action": $TOOL_NAME,
"action_input": $ACTION_INPUT
}
```
请按照这个格式:
问题:输入需要回答的问题
思考:考虑之前的和后续的步骤
动作:
```
$JSON_BLOB
```
观察:动作结果
...(重复思考/动作/观察N次)
思考:我知道该如何回答
动作:
```
{
"action": "Final Answer",
"action_input": "给人类的最终回复"
}
```
开始!提醒始终用一个有效json blob回复单一动作。必要时使用工具。如果合适,直接回复。格式是动作:```$JSON_BLOB```然后观察:。

通过 LLM_React 实现漏洞利用

tips

LLM代理人可能因多种原因而失败,包括最初不够有创意,未能成功地完成策略,以及在追求行不通的策略时“卡住”。选择初始提示对减轻这些失败情况至关重要。6

    我们表现最佳的提示鼓励模型:
    1)要有创造力,
    2)尝试不同方法,
    3)将有希望的策略进行到底,
    4)在失败时尝试新策略。

版权信息

本文原载于 not only security 复制请保留原文出处。

comments powered by Disqus